поведение sizeof () в C программировании - PullRequest
4 голосов
/ 02 мая 2020

Это моя программа ..

int main(void) {

    printf("%lu\n", sizeof(""));

    // first if else statement
    if(1 > -2) printf("Yes");
    else printf("No");

    printf("\n");

    // second if else statement    
    if( sizeof("") > -2) printf("Yes");
    else printf("No");
}

В первом printf () почему он печатает 1 как вывод, хотя я пропустил пустую строку? В первом операторе if-else я получил правильный вывод -> Да, как и ожидалось, но во втором операторе if-else он печатает outout -> Нет, может кто-нибудь объяснить мне, почему это происходит?

Мой вывод .. 1 Да Нет

Заранее спасибо: -)

Ответы [ 4 ]

5 голосов
/ 02 мая 2020

sizeof("") - один, потому что строковые литералы представляют собой символьные массивы, которые содержат заданные символы , за которыми следует '\ 0' . Таким образом, "" представляет массив символов {'\0'}.

sizeof("") > -2 - false, поскольку sizeof возвращает size_t, который является целым типом без знака. Сравнение приводит к преобразованию -2 в size_t, в результате чего оно оборачивается и становится числом, значительно большим единицы.

3 голосов
/ 02 мая 2020

Все строки в C оканчиваются \0 нулевым символом. Это означает конец укуса.

При программировании на C всегда полезно визуализировать, как данные на самом деле хранятся в памяти, как вы можете видеть здесь, «Hello» имеет длину 5 символов, однако 6 символов должны быть переданным в массив char, чтобы оставить пробел для этого нулевого символа.

Sting memory representaion in C

Вот как выглядит ваш пример, предложенный Бобом Джарвисом:

enter image description here

Что касается ложности sizeof("") > -2, взгляните на ответ sepp2k

0 голосов
/ 02 мая 2020

из C стандарта (5.2.1 наборов символов)

... Байт со всеми битами, установленными в 0 , называемый нулевым символом, должен существовать в базовом наборе символов выполнения c; он используется для завершения строки символов .

и (6.4.5 строковых литералов)

6 На этапе перевода 7, байт или код нулевого значения добавляется к каждой многобайтовой символьной последовательности, являющейся результатом строкового литерала или литералов.78) Затем многобайтовая символьная последовательность используется для инициализации массива stati c длительности и длины хранения, которых достаточно содержать последовательность.

Таким образом, каждый строковый литерал сохраняется в виде массива символов со стати c длительности хранения, включая завершающий ноль.

Пустой строковый литерал "" хранится как

char empty_literal[] = { '\0' };

и имеет тип char[1]. Следовательно, оператор sizeof для этого литерала (массива символов) выдаст значение 1 типа size_t, являющегося целым типом без знака.

Когда двоичная операция оценивается, компилятор сначала определяет их общие тип. Например, в условии оператора if

if(1 > -2) printf("Yes");

используется реляционный оператор>. Согласно стандарту C (6.5.8 Реляционные операторы)

3 Если оба операнда имеют тип арифмети c, то выполняются обычные арифметические преобразования.

Так как в условии оба операнда 1 и -2 имеют тип int, то общий тип операндов целочисленный, и, естественно, 1 больше -2. ​​

В условии В этом операторе if

if( sizeof("") > -2) printf("Yes");

первый операнд имеет тип size_t, в то время как второй операнд имеет тип int. Ранг типа size_t больше, чем ранг типа int, поэтому второй операнд преобразуется в тип size_t путем распространения знакового бита, а результирующее представление рассматривается как представление значения без знака.

Четный если тип size_t имеет тот же ранг преобразования, что и тип int, тем не менее согласно правилам обычного преобразования арифмети c объект со знаком типа int был преобразован в тип unsigned int.

Из C стандарта (6.3.1.8 Обычная арифметика c преобразования)

В противном случае, если операнд с целочисленным типом без знака имеет ранг, больший или равный рангу тип другого операнда, а затем операнд с целым типом со знаком преобразуется в тип операнда с целым типом без знака.

Вот демонстрационная программа

#include <stdio.h>

int main(void) 
{
    unsigned int x = 0;
    signed int y = -1;

    printf( "x + y > 0 is %s\n", x + y > 0 ? "true" : "false" );

    return 0;
}

Ее вывод

x + y > 0 is true
0 голосов
/ 02 мая 2020

Исходя из объяснения @ sepp2k, почему sizeof("") < -2 является верным, вот модифицированная версия вашей программы, которая четко показывает результаты:

#include <stdio.h>

int main(void) {

    printf("%lu\n", sizeof(""));

    // first if else statement
    if(1 > -2) printf("Yes");
    else printf("No");

    printf("\n");

    // second if else statement    
    if( sizeof("") > -2) printf("Yes");
    else printf("No");

    printf("\n");

    // third if else statement    
    if((long int)sizeof("") > -2) printf("Yes\n");
    else printf("No\n");

    printf("sizeof(\"\") = %lu  -2 = %d  -2 = %u\n", sizeof(""), -2, (unsigned int)-2);
}

Это выводит

1
Yes
No
Yes
sizeof("") = 1  -2 = -2  -2 = 4294967294

Как видите, когда -2 трактуется как unsigned int, оно становится очень большим числом. Чтобы понять, почему это так, вы, возможно, захотите изучить и понять представление отрицательных чисел, дополняемое двумя дополнениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...