2016-06-20 2 views
0

У меня есть одна проблема с открытым исходным кодом в указателях, которую я попытался воспроизвести в этом ниже небольшом фрагменте.проблема в двойном указателе адрес добавление

int main() 
{ 
int **a=0x0; 
printf ("a = %d Add = %d\n", a, a+75); 
return 1; 
} 

Expectation, чтобы получить 75/0x4b но этот код дает 300 в 32 бит и 600 в 64-битных машин.

Выход:

a = 0 Add = 600 

Но идеология за доступ к добавленной позиции 75-й позиции т.е. в хэш-таблице.

Так оно и должно быть

printf ("a = %d Add = %d\n", a, sizeof (a)+75); 

Но я не мог в состоянии догадаться, почему это 300 или 600 выход. может ли кто-нибудь указать?

я пошел до точки, где есть некоторый сдвиг влево внутри происходит так:

75 - 1001011 
600 - 1001011000. 

Solutions оценены. Заранее спасибо.

+0

Арифметика указателя, приводящая к обратным адресам вне существующего объекта, обычно имеет * неопределенное поведение *. –

+0

'0x0' - _null pointer_. Это не означает, что он использует представление всех битов нуль. Вы не можете направить на адрес '0' таким образом (это дефект в языке с самого его начала). – Olaf

ответ

2

Арифметика указателей всегда выполняется с использованием размера указателя. В вашем случае a является указателем на указатель на int, поэтому размер устройства равен sizeof(int*), который в вашем случае кажется 4 (32 бит). 4 * 75 = 300.

Точнее, a + 75 добавляет смещение байта sizeof(*a) * 75 (обратите внимание на разыменование a) указателю. Случается, что вы эффективно делаете &a[75], т. Е. Получаете указатель на 75-й элемент.

На небольшом примечании, когда вы печатаете указатели с printf, вы должны использовать формат "%p" и лить указатели на void *. См. this printf (and family) reference.

Что касается разного размера на 32-разрядных и 64-разрядных системах, этого можно ожидать. Указатель на 32-битной системе обычно составляет 32 бита, а на 64-битной системе - 64 бита.

+0

Но у меня есть сомнения, что здесь вы говорите об умножении (4 * 75), но то, что я сделал, есть дополнение. т. е. + 75, так как по вашему объяснению он должен быть sizeof (* a) +75 i.e 4 + 75 вправо? – Hjey

+0

Заранее спасибо @Joachim Pileborg – Hjey

+0

Следует подчеркнуть, что использование спецификатора типа строкой неправильного формата вызывает неопределенное поведение. Это не просто «незначительный недостаток» (текст вызывает это впечатление). – Olaf

1

поведение программы не определено:

  1. спецификатор формата% d не является допустимым для типов указателей: использовать% р вместо.

  2. Атрибут указателя действителен только внутри и один за последним элементом для массивов или один за адресом скаляра для скаляров. Вы не можете читать + 75.

+0

Тот факт, что вы не можете прочитать содержимое памяти, на которое указывает 'a + 75', не означает, что' Арифметика указателя равна только для массивов. Арифметика указателя действительна. Разделение указателя - другое дело. – nicola

+0

@nicola http://port70.net/~nsz/c/c11/n1570.html#6.5.6p8. Результат такой операции не определен. –

+0

@nicola: это неправда. Чтение указателя на один конец конца массива (или скаляр) определяется, но чтение указателя за ним не является. Заметьте, что я не говорю о разыменовании. –

0

Прежде всего, используйте %p для печатных указателей и %zu для sizeof результата.

Это, пожалуйста, проверьте тип a, это int **, который является величиной указателя. И это зависит от платформы/компилятора.

Указатель на арифметику присваивает тип данных, поэтому исходный указатель всегда увеличивается на основе типа данных LHS.