Странный случай при использовании оператора sizeof () в C - PullRequest
0 голосов
/ 08 октября 2011

Я тестировал использование оператора sizeof в C / C ++ с этим кодом:

#include <ctype.h>              /* Character types                       */
#include <stdio.h>              /* Standard buffered input/output        */
#include <stdlib.h>             /* Standard library functions            */
#include <string.h>             /* String operations                     */
#include <sys/types.h>          /* Data types                            */
#include <sys/wait.h>           /* Declarations for waiting              */
#include <unistd.h>   

void main()
{
  char a[100];
  char *des = malloc(100*sizeof(char));
  strcpy(des,"abcded\0");
  printf("%d\n",sizeof(des));
  printf("%d\n",sizeof(a));
  free(des);
}

Почему эта программа выводит:

4
100

В отличие от:

100
100

Ответы [ 7 ]

4 голосов
/ 08 октября 2011

Поскольку несмотря на утверждения многих людей , указатели и массивы НЕ на 100% взаимозаменяемы в C & C ++. Это яркий пример одного из отличий.

Размер указателя составляет 4 байта (или любой другой размер, зависящий от платформы), независимо от того, на какой объем выделенной памяти он может указывать.

Размер массива равен размеру массива.

3 голосов
/ 08 октября 2011

sizeof(des) возвращает размер указателя - 4 в вашей системе.Он не возвращает размер выделенного пространства, на которое он указывает.

0 голосов
/ 08 октября 2011

Ответ на этот вопрос очень прост.

Тип des - "char *" или адрес символа.Итак, вопрос, который вы задаете компилятору с помощью sizeof: «Сколько памяти (в байтах) мне нужно для хранения адреса символа?»Компилятор отвечает 4, потому что ваша программа и компилятор имеют 32-битную (4 байта) адресацию.Когда вы используете sizeof в массиве, вы задаете другой вопрос: «Сколько памяти (в байтах) мне нужно для хранения массива символов из 100 элементов?»Ответ здесь - 100 элементов * 1 байт = 100 байт.

0 голосов
/ 08 октября 2011

Я немного уточню комментарий Абеленки. Ожидаете ли вы, что эти два typedefs будут эквивалентны типам продуктов?

typedef char *string;
typedef char string[100];

Как насчет этих двух?

typedef struct { char *s; ... } header_t;
typedef struct { char s[100]; ... } header_t;

Ваш ответ явно нет в обоих случаях. Да, вы можете скомпилировать des=a, потому что a дает указатель, но a на самом деле является массивом.

В частности, вы также знаете, что этот последний typedef не резервирует память для указателя. В результате a имеет примерно тип char * const, означающий, что a является постоянным указателем на непостоянные символы, и, таким образом, a=des выдает ошибку типа. Я не знаю, будет ли упомянутое сообщение об ошибке содержать массив const или lvalue.

0 голосов
/ 08 октября 2011

Оператор sizeof возвращает номер. байтов для типа.

sizeof des дает 100, потому что тип des равен char[100], символ всегда занимает 1 байт, и их 100.

sizeof a дает 4, потому что тип a равен char*, а указатель на символ занимает 4 байта на вашей платформе (что типично для 32-битных платформ).

Итак, sizeof работает только с типом своего операнда (заметьте, sizeof - это оператор, а не функция / макрос). sizeof не взаимодействует с malloc, и тот факт, что a указывает на начало 100 динамически распределенных байтов, не имеет значения.

0 голосов
/ 08 октября 2011
printf("%d\n",sizeof(des));
printf("%d\n",sizeof(a));

эквивалентно следующему:

printf("%d\n",sizeof(char*));      //prints size of a pointer
printf("%d\n",sizeof(char[100]));  //size of a char array of size 100

Другими словами, sizeof - это оператор, который работает с типом выражения, которое вы передали ему,Поэтому, когда вы пишете sizeof(des), тип выражения равен char*, следовательно, он печатает sizeof(char*), который * 4 в вашей системе.Но в случае sizeof(a) тип выражения - char[100], следовательно, оно печатает sizeof(char[100]), то есть 100.

Здесь обсуждается более интересный случай с sizeof:

0 голосов
/ 08 октября 2011

Поскольку он возвращает размер указателя des , который указывает на выделенную память.

...