Двухсимвольный указатель C объявление и инициализация

Для модульного теста я предложил бы, чтобы Вы включали тестовый файл в свой проект (файл EAR, или эквивалентный) затем используют относительный путь в модульных тестах т.е. "../testdata/testfile".

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

25
задан vascop 28 January 2011 в 19:09
поделиться

2 ответа

char *c = "line";

- это не так же, как

char c[] = "line";

, это действительно то же самое, что

static char hidden_C0[] = "line";
char *c = hidden_C0;

, за исключением того, что переменная hidden_C0 не является прямой доступны. Но вы увидите это, если выбросите сгенерированный ассемблер (обычно он имеет имя, которое не является допустимым идентификатором C, например .LC0). И в вашем примере с массивом строковых констант происходит то же самое:

char *choices[] = { "New Game", "Continue Game", "Exit" };

становится

char hidden_C0[] = "New Game";
char hidden_C1[] = "Continue Game";
char hidden_C2[] = "Exit";

char *choices[] = { hidden_C0, hidden_C1, hidden_C2 };

Теперь, это особый случай, который доступен только для строковых констант. Вы не можете написать

int *numbers = { 1, 2, 3 };

, вы должны написать

int numbers[] = { 1, 2, 3 };

, и поэтому вы также не можете написать

char **choices = { "a", "b", "c" };

.

(Ваше заблуждение является частным случаем распространенного заблуждения о том, что массивы «совпадают» с указателями в C. Они не являются. Массивы являются массивами. Переменные с типами массивов страдают распадом типа на указатель тип, когда они используются (почти в каждом контексте), но не когда они определены.)

16
ответ дан 28 November 2019 в 21:27
поделиться

Онлайн-стандарт C (черновик n1256 ):

6.7.8 Инициализация
...
11 Инициализатором для скаляра должно быть одиночное выражение , необязательно заключенное в фигурные скобки. Начальное значение объекта - это значение выражения (после преобразования); применяются те же ограничения и преобразования типов, что и при простом присваивании, принимая тип скаляра за неквалифицированную версию его объявленного типа.
...
16 В противном случае инициализатор для объекта, который имеет агрегатный или объединенный тип , должен быть заключенным в скобки списком инициализаторов для элементов или именованных членов.

Выделение добавлено.

char ** является скалярным типом, а не агрегатом, и поэтому не совместим с инициализатором {"New Game", "Continue Game", "Exit"}. Напротив, char *[] является агрегатным (массивом) типом.

Аналогично, вы не могли написать что-то вроде

int *foo = {1, 2, 3};

, потому что int * не является типом массива.

Ваше понимание

char *c = "line";

и

char c[] = "line";

слегка отклонено; они не одинаковы. Первая форма копирует адрес строкового литерала в значение указателя c. Вторая форма копирует содержимое выражения массива "line" в буфер, обозначенный c. [Тысяча сто тридцать одна]

2
ответ дан 28 November 2019 в 21:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: