Общее количество Ruby
a=["and a partridge in a pear tree","turtle doves","French hens","calling birds","golden rings","geese a-laying","swans a-swimming","maids a-milking","ladies dancing","lords a-leaping","pipers piping","drummers drumming"]
b=["","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve"]
c=["first","second","third","fourth","fifth","sixth","seventh","eighth","nineth","tenth","eleventh","twelfth"]
0.upto(11){|d|puts "On the "+c[d]+" day of Christmas, my true love gave to me:\n"+b[d]+" "+a[d]+",";(d-1).downto(0){|e| f=", ";f = "." if e==0;puts b[e]+" "+a[e]+f;}}
: 593 байта с помощью UNIX LF.
Если вы явно не напишете & a
, он не будет нигде сохранен. Если вы все же пишете, адрес будет вычислен и сохранен либо в безымянной переменной (временной), либо в именованной переменной, которую вы пишете.
Например:
functionCall( &a ); // address will be in a temporary variable used for passing the parameter
int** b = &a; // address will be stored in variable b
otherFunctionCall( &&a ); // illegal, since &a is an expression operator & can't be applied to it
a
не является «адресом, в котором можно хранить целое число». a
- это переменная, достаточно большая, чтобы содержать адрес целого числа. Единственное «целое число», которое вы можете сохранить непосредственно в a
, - это адрес целого числа, рассматриваемого как само целое число:
int *a;
int b;
a = &b;
printf("a is now %x\n", (unsigned int) a);
Это правильно, что a
сам имеет адрес, который это & a
, но этот адрес не сохраняется где-то явным образом во время выполнения.
На некотором отрезке вы можете сохранить что-то, что выглядит как целое число 0:
a = 0;
Но это всего лишь сокращенный синтаксис для «указателя NULL», т.е. значение указателя, гарантированно не являющееся адресом какого-либо фактического объекта.
int * a
- это переменная размером с указатель, точно так же, как int b
будет автоматической переменной int.
Если это объявление находится в функции, эта переменная будет автоматической и хранится в стеке [
] ( http://en.wikipedia.org/wiki/Stack_ (data_structure) #Hardware_stacks) во время выполнения (простой декремент стека выделяет память для него).
Если объявление является глобальным, то «a» просто отображается в области .DATA
исполняемого файла.
Дополнительные добавленные знаки & могут «создать хранилище», потому что временных переменных, которые вы используете для холдема;):
b = &a; //the address in the executable's .DATA or on the stack (if `a` auto)
c = &b; //the address of `b` on the stack, independent of `a` or `&a`
d = &c; //the address of `c` on the stack, independent of `a` or `&a`
z = &(&a); //error: invalid lvalue in unary '&'
Последняя строка жалуется на тот факт, что &
требует, чтобы операнд был lvalue
. То есть что-то присваиваемое, например b
и c
выше.
Вы можете продолжать бесконечно:
int value = 742;
int *a = &value;
void *b = &a;
void *c = &b;
void *d = &c;
Вы бы не поместили его в одну строку, не назначив его чему-либо - в этом случае он будет недействительным.
& a - адрес а. Это значение, результат применения оператора & к a, оно не "хранится" и не имеет адреса, поэтому & (& a) недопустимо. Это как 2 + 3.
Суть вашей проблемы, похоже, заключается в отсутствии понимания физической природы памяти и указателей. Не то, как работает код. Как я уверен, вы знаете, что физическая память состоит из большой группы смежных ячеек. Адреса этих ячеек фиксируются и жестко запрограммированы самим компьютером, а не программными приложениями или языком программирования, который вы используете. Когда вы ссылаетесь на & a, вы имеете в виду физический блок памяти, который в настоящее время содержит ваше значение, которое вы сохранили в оперативной памяти компьютера. «a» - это просто имя, которое вы дали компьютеру, чтобы он точно знал, в каком блоке памяти найти значение, которое вы сохранили. Я думаю, это в значительной степени покрывает адрес памяти.
Теперь перейдем к указателям. Указатель - это еще один адрес памяти, на который ссылается компьютер. У него есть любое имя, которое вы ему дадите. В этом случае его следует называть чем-то еще, кроме того имени, которым вы дали свое первое значение. Назовем это "б". Исходя из того, как вы это заявили. Ячейка памяти b способна хранить только один тип данных ... другую ячейку памяти ... поэтому, когда я говорю: b = & a, я говорю, что адрес памяти 'b' (который предназначен только для хранения адреса памяти), должен содержать адрес памяти 'a'. Между тем, на другом конце города в адресе памяти «a» хранится целое число.
Я надеюсь, что это не запутало, я старался не тратить на вас всю техно-болтовню. Если вы все еще в замешательстве. Отправьте еще раз, в следующий раз я объясню с кодом.
Не совсем так. a
- это переменная, в которой может храниться адрес некоторого целого числа. & a
- это адрес a
, то есть адрес переменной a
, которая может содержать адрес некоторого целого числа.
Очень важно: до и если адрес чего-либо не назначен a
, это неинициализированный указатель. Попытка использовать то, на что он указывает, приведет к непредсказуемым результатам и, скорее всего, приведет к сбою вашей программы.
В C переменная x
может действовать как значение (в правой части =, где она называется rvalue ), или он может действовать как контейнер для значений (в левой части =, где он называется lvalue ). Вы можете взять адрес x
, потому что вы можете взять адрес с любым lvalue - это даст вам указатель на контейнер. Но поскольку указатель - это rvalue, а не контейнер, вы никогда не сможете взять & (& x)
. Фактически для любого lvalue l
, & l
допустимо, но & (& l)
никогда не является допустимым.
a - это переменная типа "адрес int"; & a - адрес переменной a; & (& a) будет адресом адреса переменной a, что не имеет смысла
У вас может быть указатель на указатель.
Пример:
void foo(int **blah)
{
int *a = *blah;
...
}
Указатель занимает память. Это просто небольшой контейнер, в котором хранится адрес чего-либо. Он просто не может занимать «пустое место», потому что все в компьютере каким-то образом представлено числами. Просто, если говорить о C / C ++, int * a - это просто указатель на объект и не занимает места. Это сделано для того, чтобы вам не приходилось управлять какой-либо памятью ... она отделяет машину от кода.
int * a; указатель на int с именем 'a'. & a; это разыменование int * a. он указывает на себя. это то, что вы должны использовать, чтобы указать на переменную, которую вы хотите передать от функции к функции. derefrence - это просто причудливое слово для "вернуть адрес" & (& (& a)) не является допустимым выражением, как указывалось ранее. вы можете сделать указатель на указатель на указатель. Возможно, вы об этом думаете. В таком случае вы разыграете последний рассматриваемый указатель, и компьютер должен понять, о чем вы говорите.
Чтобы ответить на вопрос «где хранится»; в стеке.
пожалуйста, если я в чем-то ошибаюсь, дайте мне знать.
int* a;
This line simply declares a pointer to an integer. That pointer has a memory location, which you can get the address of using &a. & is an operator that returns the address of whatever it is run on. But if you do not assign this value anywhere, there is no further &-ing possible.
As to your question as to where &a is stored, most likely in a register. If you do not use the value, it will be immediately discarded. (And registers do not have memory addresses, which is why you cannot do &(&a))
& a - это число, которое является r-значением: вы можете сохранить его где-нибудь, если хотите, в объявленной или выделенной вами переменной типа int *.
То есть:
int a = 42;
&a; /* this does not store the address of a because you've not assigned the value to a variable */
int **aptr = &a; /* aptr is on the stack */
int **aptr2 = (int*)malloc(sizeof(int*));
aptr2 = &a; /* aptr2 is in the heap */
& (& a) - это не юридический синтаксис. If you want a pointer to a pointer to an int:
int b = 39;
int *bptr = &b;
int **ptr2bptr = &bptr;
You have to build up the levels of indirection.
With the above you can then do this if you want:
printf("%d\n", *aptr);
printf("%d\n", *aptr2);
printf("%d\n", *bptr);
printf("%d\n", **ptr_to_bptr);
Producing output of:
42
42
39
39