#include <stdio.h>
#include <stdlib.h>
void process_keys34 (int * key3, int * key4) {
*(((int *)&key3) + *key3) += *key4;
}
int main (int argc, char *argv[])
{
int key3, key4;
if (key3 != 0 && key4 != 0) {
process_keys34(&key3, &key4);//first time
}
if (true) {
process_keys34(&key3, &key4);
msg2 = extract_message2(start, stride);//jump to here
printf("%s\n", msg2);
}
}
Я тестирую этот код на macOS 10.12, используя Xcode7.Почему p & key3 + 2 и p (int *) & key3 + 2 будут печатать разные результаты в LLVM?
Вопрос можно описать просто как
Почему &key3 == (int*)&key3
но &key3 + 2 != (int*)&key3 + 2
и &key3 + 2 == (int*)&key3 + 4
при использовании XCode7
Я установил KEY3 и КЛЮЧ4 из ARGV, Я хочу прыгать с process_keys34(&key3, &key4);//first time
до
msg2 = extract_message2(start, stride);//jump to here
.
Поэтому я должен изменить значение обратного адреса func process_key34. Поскольку существует ключ var4 между & key3 и адресом возврата, поэтому я должен добавить 2 к & key3, что означает, что key3 должен быть 2. Но правда в том, что key3 должен быть 4, тогда результат правильный.
Затем выполните некоторые испытания в lldb. я обнаружил, что
(lldb) p *(&key3 + 2)
(int *) $6 = 0x0000000100000ec3 //that's right.
но
(lldb) p *((int*)&key3+2)
(int) $8 = 1606416192// I dont know what does that mean.
я проверить, что
(lldb) p &key3
(int **) $5 = 0x00007fff5fbff6d8
(lldb) p (int*)&key3
(int *) $7 = 0x00007fff5fbff6d8
Я нашел эти две такие же.
но &key3 + 2 ,(int*)&key3 + 2
отличаются друг от друга.
(lldb) p &key3 + 2
(int **) $9 = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 2
(int *) $10 = 0x00007fff5fbff6e0
и &key3 + 2 ,(int*)&key3 + 4
такие же
(lldb) p &key3 + 2
(int **) $9 = 0x00007fff5fbff6e8
(lldb) p (int*)&key3 + 4
(int *) $14 = 0x00007fff5fbff6e8
Я обнаружил, что & ключ3 является INT ** и (интермедиат *) & ключ3 является INT *, который является единственным различием между этими двумя командами. Но я все еще не понимаю, почему это произошло.
Поскольку в результате сближения с C99 правая часть + изменится на один и тот же тип слева, это означает, что intger 2 будет чередоваться с int * или int **. Но я думаю, что они не имеют разницы, потому что sizeof (int *) == sizeof (int **).
Я не знаю, почему это произошло. Может ли кто-нибудь мне помочь?
Код вызывает неопределенное поведение, используя неинициализированные переменные. Я думаю, из ваших комментариев, что «реальный код» отличается и инициализирует переменные. Но даже в этом случае код продолжает вызывать неопределенное поведение из-за доступа вне границ. В C или C++ не разрешено выполнять арифметику указателя по адресу переменных и тем самым получать доступ к другой переменной. Чтобы сделать это, вы должны использовать массив. –
Представьте, что вы рассматриваете вещи как массивы. int * будет похож на массив ints, int ** больше похож на массив int *. По мере того, как работает указатель math, int * + 2 будет увеличиваться на 2 * sizeof (int). int ** + 2 будет увеличиваться на 2 * sizeof (int *). Первый, скорее всего, «2 * 4», а последний, скорее всего, «2 * 8» на 64-битной платформе. – Charlie
Связанный: http://stackoverflow.com/questions/394767/pointer-arithmetic – alk