C/C++

Структуры и строки в си

 #include  
#include
#include
#include

struct spis { char FIO_advocate[23]; } *head;

char name_advocate[23];

char list(struct spis *p) {
char num_s[23];
strcpy(num_s, p->FIO_advocate);
return num_s[23];
}

void copy() {
head = (struct spis *)malloc(sizeof(struct spis));
strcpy(name_advocate, list(head); // 18-ая строка
}

int main() { return 0; }
Первая функция list компилируется без ошибок, во второй функции copy, где я хочу присвоить символьному массиву значение функции list происходит ошибка в 18-ой стороке:
[Warning] passing argument 2 of 'strcpy' makes pointer from integer without a cast [-Wint-conversion]

Что мне изменить, спасибо за ответы?
Функция list возвращает 23-й элемент массива num_s типа char, которое является 8-битовым целым числом, о чём компилятор и предупреждает. Но он не предупреждает, что этот элемент находится ещё и за границей массива, потому что в массиве размерностью 23 последний элемент имеет индекс 22 (отсчёт идёт от нуля). Надо возвращать char*, но указатель не на массив, распределённый в стеке и удаляемый после возврата из функции, а на динамически распределённый массив (malloc), переданный в эту же функцию по указателю в качестве аргумента, глобальный или статический.

Но и в функции copy тоже ошибка. Там распределяется память под head и тут же копируется как zero-строка в name_advocate. Результат работы такого кода неопределённый: если в распределённых 23 байтах случайно окажется 0, то скопируется мусор до этого нуля. Иначе скопируется более 23 байтов (тоже мусора), затерев что-то ещё, что может привести к падению программы.

Наконец, в main ни одна из этих функций не вызывается.

Если нет веских причин начинать обучение программированию именно с си, то я рекомендовал бы начать с паскаля или golang, а потренировавшись на них, перейти к си. Си - очень хороший язык, но в нём много подводных камней для новичка.
Евгений Лемермаер
Евгений Лемермаер
4 819
Лучший ответ
Вадим Долбня спасибо большое, да, в моем коде я по хеду присвоил значение строке и уже потом его копировал, первый отвечающий, за что ему тоже спасибо, также сказал про *char, буду знать, и как я не понял что ретерт num_s[23] не возвращает строку и даже её часть из-за последнего индекса 22
 #include  
#include
#include
#include

#ifdef __unix__
#define _countof(a) (sizeof(a)/sizeof(*(a)))
#endif

typedef struct node {
char name[32];
struct node* next;
} Node, *NODE, *LIST;

LIST list = NULL;
size_t count = 0;

NODE create(NODE node) {
if (node != NULL) {
// инициализация полей элемента списка
// здесь требуется обработать все ошибки ввода данных
printf("Name: ");
fgets(node->name, _countof(node->name), stdin);
node->name[strlen(node->name) - 1] = 0;
} else {
puts("Error: not enough memory!");
}
return node;
}

void add() {
NODE node = (NODE)malloc(sizeof(Node));
node = create(node);
if (node == NULL) return;
++count;
if (list == NULL) {
list = node;
list->next = NULL;
} else {
NODE begin = list;
while (begin->next != NULL) {
begin = begin->next;
}
begin->next = node;
begin->next->next = NULL;
}
}

_Bool empty(void) {
return list == NULL;
}

void pop_back(void) {
if (list != NULL) {
NODE begin = list;
if (begin->next == NULL) {
free(begin);
list = NULL;
return;
}
while (begin->next->next != NULL) {
begin = begin->next;
}
free(begin->next);
begin->next = NULL;
--count;
}
}

void clear(void) {
while (list != NULL) {
pop_back();
}
}

void show(void) {
if (list != NULL) {
NODE begin = list;
while (begin != NULL) {
printf("%s\n", begin->name);
begin = begin->next;
}
}
}

size_t size(void) {
return count;
}

int main(void) {
const char* dotted = "----------------";
add();
add();
add();
puts(dotted);
show();
puts(dotted);
pop_back();
show();
puts(dotted);
clear();
if (list == NULL) {
puts("List empty!");
}
return 0;
}
Myrzabek Duismaganbetov
Myrzabek Duismaganbetov
87 657
Вадим Долбня я просто уже боюсь ваших ответов, но спасибо большое
[Предупреждение] передача аргумента 2 из 'strcpy' создает указатель из целого числа без приведения типов [-Wint-conversion]
Неподходящий для аргумента ТД. Конвертируй int32 в string
Вадим Долбня это то всё круто, но я тупой и мне не достаточно просто прочитать ошибку для решения проблемы
 char list(struct spis *p) {  // возвращается символ вместо строки
char num_s[23]; // эта локальная переменная будет уничтожена в момент вызова return, который вернет указатель на стек, где будет лежать уже нечто случайное
strcpy(num_s, p->FIO_advocate);
return num_s[23]; // нельзя возвращать локальную переменную, нет смысла возвращать один символ, в массиве num_s[23] нет элемента с номером 23
}
Весь код - кусок мусора, который вообще не стоит обсуждать или как-то исправлять. Все выкидываете и начинаете читать учебник с самого начала
Вадим Долбня так я же и так сказал что это мусор хД