Кто-то поднял этот код до меня, что заставило меня задуматься, что там происходит код выглядит следующим образом из VS 2019:
#include <stdio.h>
#include <string.h>
int main()
{
char y = '5';
char w = "5";
printf("size of x %x\n",&w);
printf("size of X %X\n", w);
printf("size of X in number: %d \n", w);
printf("size of Y %d\n\n", w);
w = '5';
printf("size of y %x\n", &w);
printf("size of Y %X\n", w);
printf("size of X in number: %d \n", w);
printf("size of Y %d\n\n", w);
return 0;
}
Вывод выглядит следующим образом:
size of x 8ff8bb
size of X 30
size of X in number: 48
size of Y 48
size of y 8ff8bb
size of Y 35
size of X in number: 53
size of Y 53
Интересно, что там происходит на самом деле? кто-то указал, что 'является символом, а "является строкой, но если это так, почему здесь можно поместить строку в символ, и почему это результаты?
Спасибо за ответы Я понимаю, что это может быть не слишком актуально для использования, но мне интересно, что там происходит, я только недавно вернулся, чтобы переучить C
Код скомпилирован и не выдает предупреждений в VS2019.
Поиск Google в основном дает мне результаты о том, как помещать символы в массив и тому подобное, не смог найти никакой информации об этом поведении.
Это ничего не может вывести, так как это не компилируется.
Этот код не имеет никакого смысла по отношению к тексту, который он печатает.
Я должен был отредактировать его, опубликовать код, как он был дан
char w = "5";
выдаст предупреждение и, скорее всего, не сделает то, что вы думаете.
Я знаю, что это то, что должно произойти (не компилировать), но, как кажется, VS, по крайней мере, компилирует его. Теперь я заметил, что поставил VSCode .. мой плохой, имел в виду VS не код
Код, который вы разместили, компилируется как надо. Но выдает предупреждение.
Выходной текст, похоже, не имеет никакого отношения к печатаемым значениям. Например, последние два printf
в каждой группе, очевидно, печатают одно и то же число, но имеют разный текст.
Когда программа бессмысленна, нет смысла пытаться понять, что она делает.
Правильное исправление действительно выдает предупреждение, но не при вводе строки в char, а в printf
Почему вы сделали свой вывод таким запутанным? Вы печатаете «размер X», чтобы показать значение w
. Почему ты так усложняешь? Кого ты пытаешься запутать?
@ChristianGibbons может быть, но это заставляет меня задуматься, протестировал его на нескольких компьютерах, чтобы увидеть, и результаты, похоже, остаются неизменными, мне сказали, что на более старом компиляторе он не скомпилируется (также VS). Кроме того, результат остается прежним заставляет меня задаться вопросом, действительно ли это просто случайность или за этим стоит какой-то смысл, даже если это бесполезно, интересно узнать
В любом случае, без обид, но нет смысла объяснять, почему этот код ведет себя именно так. Вы должны найти учебник о строках в C и прочитать его.
char w = "5";
определяет строковый литерал "5"
и присваивает его адрес (где находится символ '5'
) переменной char w
, усекая значение указателя до char
. Выходное значение 0x30
(шестнадцатеричное) или 48
(десятичное), вероятно, означает, что это значение имеет младший байт адреса строкового литерала.
@JonathanWood Его код отправлен мне, сохраните его в исходном коде, имена, которые я предполагаю, сделаны для тестирования кода, не утруждая себя внесением изменений в печатную информацию.
@Bodo Я не уверен, что это правда, что значение указателя усекается. Если char
является подписанным типом, то он должен переполняться, что, как мне кажется, приводит к неопределенному поведению.
Возможный дубликат: «Указатель из целого числа/целое число из указателя без приведения».
@ChristianGibbons Неопределенное поведение не означает, что оно не усекается. Он может делать все что угодно, в том числе и оборачиваться.
@Arkku Я не хотел, чтобы это не могло привести к переносу, а скорее к тому, что ожидать усечения ненадежно (если только вы не знаете, что работаете в системе, где char
не имеет знака). Таким образом, пытаться понять это бессмысленно.
Строка представляет собой массив символов, оканчивающихся символом NUL. Данные здесь:
"5"
Это то же самое, что:
{'5','\0'}
Когда вы присваиваете значение массива чему-то в C, вы назначаете указатель на первый элемент в массиве. Итак, когда вы пишете:
char w = "5"
вы создаете символ и присваиваете его значение ячейке памяти первого элемента в массиве символов, символ недостаточно велик для хранения ячейки памяти.
Делая это:
printf("size of x %x\n",&w);
Распечатывает местоположение w в памяти
Делая это:
printf("size of X %X\n", w);
печатает значение w, в вашем случае было присвоено адресу массива строк и усечено, потому что char не может соответствовать адресу.
Если вы хотите использовать строку, вы должны сделать это:
const char * w = "5"
Затем вы можете распечатать строку следующим образом:
printf("string: %s\r\n", w);
вы можете распечатать первый символ в массиве одним из этих способов
printf("char: %c\r\n", *w);
printf("char: %c\r\n", w[0]);
Для второго бита, когда вы назначаете w следующим образом:
char w = '5';
печать &w
печатает местоположение в памяти.
печать w
с %x
печатает значение ASCII '5'
, которое равно 0x35
Спасибо за ответ, думаю, это действительно просто усечено, тогда
Инициализация
char w = "5";
делает две вещи:
"5"
, который представляет собой некоторую область памяти, содержащую '5'
, за которой следует NUL
('\0'
).w
типа char
и инициализируйте ее адресом строкового литерала, то есть адресом памяти, где находится '5'
. Адрес (указатель) преобразуется в char
, что приведет к потере части значения, поскольку char
обычно меньше указателя (char*
).С участием
printf("size of X %X\n", w);
вы печатаете значение char w
в шестнадцатеричной форме, которое, вероятно, является младшим значащим байтом адреса строкового литерала.
Вам лучше использовать
printf("size of X %X\n", (unsigned int)w); /* %X = unsigned int */
или
printf("size of X %hhX\n", w); /* %hhX = unsigned char or signed char */
чтобы формат соответствовал типу аргумента.
Даже если это не изменит результат в вашем случае, это гарантирует, что код printf
не получит доступ к памяти, которая возможно неинициализирована или может содержать несвязанные данные.
Когда я запустил ваш код, в одном случае значением w
было 0xA8
, которое было напечатано как FFFFFFA8
. В этом случае %hhX
напечатает только A8
.
Я не уверен, что именно произойдет, когда вы передадите значение char
функции printf
, в то время как формат указывает функции интерпретировать данные как unsigned int
. Это может зависеть от соглашений о вызовах вашей платформы и реализации компилятора. Возможно, на вашей платформе все аргументы более коротких типов данных преобразуются в int
или unsigned int
.
Выполнение printf("size of X %hhX\n", w);
и printf("size of X %X\n", (unsigned int)w);
дает тот же результат, что и раньше. Спасибо за ответ.
"size of x %x\n",&w
- За исключением того, что он не печатает размер, поскольку&w
не является размером чего-либо.