Учитывая `int num [7]`, чем отличаются `num`,` & num [0] `,` & num`? - PullRequest
11 голосов
/ 28 августа 2011

Я читал в книге C, что для массива num[7] термин num эквивалентен &num[0].Эта концепция работала нормально для меня, но когда я написал эту программу, показанную ниже, я снова запутался.

#include<stdio.h>
#include<conio.h>
int main()
{
    int num[]={21,22,23,24,25,26,27};
    int *x,*y,*z;
    x=&num;
    y=num;
    z=&num[0];
    printf("%d   %d   %d\n",sizeof(x),sizeof(y),sizeof(z));
    printf("%d  %d  %d\n",sizeof(&num),sizeof(num),sizeof(&num[0]));
    printf("%d   %d   %d",*(&num),*(num),*(&num[0]));
    getch();
    return 0;  
}

вывод:

      4    4    4
      4    28   4
      2293536   21   21

Если num идентичен &num[0] тогда почему есть разница в их размере?И что это за третий тип термина &num?Я знаю, что это показывает значение мусора, но имеет ли смысл этот тип термина?z=&num[0] Я уже понимаю.Компилятор показывает предупреждение для присваивания x=&num, но для y=num; компилятор не имеет никаких проблем.Если num имеет размер 28, то почему он был назначен целочисленному указателю y без преобразования типа?

Тогда я попробовал 2-й массив таким образом:

#include<stdio.h>
#include<conio.h>
int main ()
{
    int s[4][2]={{1234,56},{1235,57},{1236,58},{1237,59}};
    int i
    printf ("\n%d %d %d %d %d",sizeof(s[i]),sizeof(&s[i]),sizeof(s),
        sizeof(s[0][0]),sizeof(&s));
    getch();
    return 0;
}

Теперь вывод равен

8  4  32  4   4

Здесь sizeof(s[i]) равно 8.потому что s[i] является одномерным массивом и имеет два элемента, так что все в порядке.Но я понятия не имею, что означают термины &s[i] и &s.И я снова вижу, что s не совпадает с s[0][0].Я использовал версию Dev C ++ 4.9.9.2 для запуска всех программ.Я хочу быть ясным в этих трех типах терминов.

Ответы [ 4 ]

5 голосов
/ 28 августа 2011

Хорошие вопросы здесь. Надеюсь, мы все сможем объяснить вам эти проблемы.

Учитывая

int num[]={21,22,23,24,25,26,27};

Тогда

  • num имеет тип int[], потому что это объявленный массив целых чисел, чья память распределена на месте. Обратите внимание, что не имеет тип int*, что было бы так, если бы вы использовали его неправильно.
  • sizeof(num) равно 28, потому что num - это массив из 7 дюймов, размер которого на вашем компьютере составляет 4 байта. Значение будет 56, если целые числа были 8 байтов, или 14, если они имели 2 байта, но наиболее распространено 4 байта на целое число.
  • &num[0] - указатель типа int*, чье значение является адресом первого элемента num.
  • Размеры x и друзей равны 4, потому что они объявлены как указатели, которые на вашем компьютере под вашим компилятором C указатели выделяются в 4 байта.

Следует иметь в виду, что когда массив используется в определенных контекстах, например, передается в качестве параметра, он преобразуется в int*. Вот почему вы можете сказать *num и получить 21. Хитрый, но это так. Вот почему обычно можно поменять местами num и &num[0], но вы действительно должны помнить о различии, потому что, как вы заметили, значения sizeof отличаются.

Преобразование - вот почему y = num имеет смысл. y имеет тип int*, а в C вы получаете автоматическое преобразование из int[] в int*. Вы не можете сделать x = &num, потому что тип &num - это «указатель на массив int». Вы не можете присвоить это int* (указатель на int).

В случае

int s [4] [2] = {{1234,56}, {1235,57}, {1236,58}, {1237,59}};

У нас есть тип s как int[][], тип &s как pointer to int[][] и тип &s[i] как указатель на int[] (потому что s[i] является массивом int). Благодаря тому, что C позволяет назначать / передавать массивы указателям, вы можете играть в те же игры, что и в первом примере.

Вы заметите, что s, &s[0] и &s[0][0] все указывают на одни и те же области памяти, но, как вы заметили, значения sizeof будут отличаться.

3 голосов
/ 28 августа 2011

Теперь мой вопрос: если num совпадает с & num [0], то почему разница в размере там?

num - это массив. sizeof имеет иногда удивительное поведение для массивов, заключающееся в том, что он сообщает вам размер хранилища всего массива, если вы передаете ему фактический массив, но он сообщает вам только размер указателя на элемент в массиве, если вы передаете это адрес такого элемента. Это может привести к путанице, потому что имя массива уменьшается до указателя в вызовах функций.

Итак, ответ таков: num не идентичен &num[0] - последний является адресом первого элемента num, с любой информацией об общем размере удаленного массива. Эти две вещи взаимозаменяемы во многих контекстах, например, при вызове реальных функций, но не при вызове sizeof (который является не функцией, а специальным ключевым словом, обрабатываемым компилятором).

3 голосов
/ 28 августа 2011

Ваши противоречия действительны. Это не случай, когда num эквивалентно &num[0]. Это просто ложь. Массивы отличаются от указателей, и num относится к объекту с типом int[7], а не int*. Вот почему размер отличается, например, потому что один представляет собой непрерывный набор из семи целых чисел.

Обратите внимание, что при необходимости num может быть преобразовано в int* со значением &num[0]. Конечно, конверсия - это не то же самое, что эквивалентность. Вы найдете эту путаницу между массивами и указателями странным образом, потому что люди продолжают повторять ложь, что массивы являются указателями. Это не так.

2 голосов
/ 28 августа 2011

Ого, это много вопросов за один раз: P

Сначала я попытаюсь объяснить вам этот вывод:

  4    4    4
  4    28   4
  2293536   21   21

sizeof() является унарным оператором в c.Он заменяется целым числом при компиляции кода, а не во время выполнения.Таким образом, компилятор буквально меняет ваш printfs на:

 printf("%d   %d   %d\n", 4, 4, 4);
 printf("%d  %d  %d\n", 4, 28, 4);
 printf("%d   %d   %d",*(&num),*(num),*(&num[0]));

На очень ранней стадии компиляции.

Компилятор достаточно любезен, чтобы дать вам размер всего массива при написанииsizeof(num).Вот как sizeof определяется для работы с массивами.Все остальные элементы дают вам размер (int *), кроме sizeof (& num), который дает вам размер (int **) (в любом случае int ** такой же, как int *).

  • & num - это место в памяти указателя на ваш массив
  • num, а & num [0] - это место в памяти первого целого в вашем массиве

На ваш второй вопрос;

printf("\n%d %d %d %d %d",sizeof(s[i]),sizeof(&s[i]),sizeof(s),sizeof(s[0][0]),sizeof(&s));

sizeof(s[i]) - size of an array (int[2]) == 8
sizeof(&s[i]) - size of a pointer to an int array sizeof(int **) == 4
sizeof(s) - size of a 2D array containing 8 ints == sizeof(int[8]) == 32
sizeof(s[0][0]) - size of an int === 4
sizeof(&s) - size of a pointer to an array == 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...