Страницы

Поиск по вопросам

среда, 10 апреля 2019 г.

При передаче массива строк в функцию строки равны NULL

Есть непонятная проблема по передача массива строк в функцию на языке Си.
Вызывающий код:
char str[33][40]; CreateCSV((char**)str);
Функция:
void CreateCSV(char** str) { char strData[]= {'"','Д','А','Т','А','"',';','\0'};
if(str[0x00] != NULL) strcpy (str[0x00], strData); else Console("СтрокаЗаголовка[0x00] == NULL"); }
Почему у меня str[0x00] == NULL? Ведь я явно создал 33 строки и зарезервировал по 40 символов под каждую.


Ответ

Если в кратце - используйте одинаковый прототип для объявления переменной и для параметров в функции и для strData. Это не самый красивый вариант, но он сработает
Вот как будет выглядеть Ваша программа:
#include #include
void CreateCSV(char str[33][40]) { char strData[33][40]= {"\"","D","A","T","A","\"",";","\0"};
if(str != NULL) memcpy (str, strData, sizeof(strData)); else printf ("error
"); }
int main (void) { char str[33][40] = {'\0'}; int i=0;
CreateCSV(str);
for (i=0; i<33; i++) printf ("%s
", str[i]);
return 0; }
Обратите внимание на сл. нюансы - я использовал функцию копирования памяти а не строк "memcpy". И проверял на NULL имя str без указания сдвига. Это связано с тем, как язык Си представляет и обрабатывает многомерные массивы. Также при заполнении strData использовал двойные кавычки, иначе компилятор соединял буквы в одну строку, а не трактовал их как ряд строк с 1 буквой в каждой строчке.

Если в деталях и особенностях физики языка Си: Массивы объявленные как
char str[33][40];
и как
char str**;
это совершенно разные вещи.
char str[33][40]; - трактуеться как длинный одномерный массив глде все строки слеплены в одну одна-за-другой. Что-то ввиде "строка 1 \0\0\0\0\0...\0 строка 2 \0\0\0\0\0...\0 ....... строка 33 \0\0\0\0\0...\0 " и размер такого массива будет равер 33*40*sizeof(char)=33*40*1=1320.
При объявлении такого массива, компилятор выделяет 1320 байт в стеке, и трактует переменную 'str' как указатель на эту длинную строку.
char str;** - это массив указателей на одномерные строки. Воспринимаеться компилятором как {*pointer_to_str1, *pointer_to_str2, ... *pointer_to_str33}, при этом сами строки лежат вне этого массива. Размер такого массива будет равен 33*sizeof(char*) = 33*4 = 132/
При объявлении такого массива, компилятор проводит несколько операций. Сначала компилятор выделит 33 независимых строки в стеке , затем создаст массив указателей и заполняет его указателями на эти 33 независимые строки.
Вот как будет выглядеть Ваша программа если strData объявить как char**:
#include #include
void CreateCSV(char str[33][40]) { char *strData[33] = {"\"","D","A","T","A","\"",";","\0"};
if(str != NULL) { int i=0; for (i=0; i<33; i++) if (strData[i] != NULL) strncpy (str[i], strData[i], 40); } else printf ("error
"); }
int main (void) { char str[33][40] = {'\0'}; int i=0; CreateCSV(str); for (i=0; i<33; i++) printf ("%s
", str[i]); return 0; }
PS оба примера проверены на gcc

Комментариев нет:

Отправить комментарий