Для модульного теста я предложил бы, чтобы Вы включали тестовый файл в свой проект (файл EAR, или эквивалентный) затем используют относительный путь в модульных тестах т.е. "../testdata/testfile".
, пока Ваш проект правильно экспортируется/импортируется, чем Ваш модульный тест должен работать.
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. Они не являются. Массивы являются массивами. Переменные с типами массивов страдают распадом типа на указатель тип, когда они используются (почти в каждом контексте), но не когда они определены.)
Онлайн-стандарт 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
. [Тысяча сто тридцать одна]