почему первый выводит строковое значение, а второй дает segfault?
Что происходит в случае I:
Тип staticArray
равен char [100]
, т. Е. Массив 100
char
.
Тип &staticArray
равен char (*)[100]
.
%s
спецификатор формата в scanf()
ожидает аргумент как указатель на начальный элемент массива char
, то есть типа char *
.
Вы передаете тип char (*)[100]
в scanf()
, следовательно, компилятор выдает предупреждение в этом операторе.
&staticArray
дает вам указатель на массив типа char (*)[100]
, который численно 1034 * совпадает с базовым адресом массива.
Учтите это пример:
#include <stdio.h>
int main(void)
{
char staticArray[100];
printf ("staticArray: %p\n", (void*)staticArray);
printf ("&staticArray : %p\n", (void*)&staticArray);
return 0;
}
Вывод:
## ./a.out
staticArray: 0x7ffee4044a70
&staticArray : 0x7ffee4044a70
staticArray
и &staticArray
оба дают указатель на один и тот же адрес 1) , но их тип отличается . Вот почему, когда вы передаете &staticArray
в scanf()
, получая предупреждение во время компиляции из-за несоответствия типов, но когда вызывается scanf()
, он обрабатывает этот указатель как char *
и читает ввод и сохраняет результат в заданном месте. При печати позже она печатает строковое значение.
Что происходит в случае II:
Тип dynamicArray
равен char *
.
Тип &dynamicArray
равен char **
.
Итак, вы передаете char **
type в scanf()
, который ожидает char *
при использовании спецификатора формата %s
. Следовательно, компилятор предупреждает об этом. Указатель &dynamicArray
отличается от dynamicArray
.
Рассмотрим этот пример:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* dynamicArray;
dynamicArray = malloc(sizeof(char)*100);
if (dynamicArray == NULL) {
exit(EXIT_FAILURE);
}
printf ("dynamicArray: %p\n", (void*)dynamicArray);
printf ("&dynamicArray : %p\n", (void*)&dynamicArray);
free(dynamicArray);
return 0;
}
Вывод:
## ./a.out
dynamicArray: 0x7fd615401690
&dynamicArray : 0x7ffee7ab7ad0
dynamicArray
и &dynamicArray
оба даст другой указатель .
Когда вы передаете &dynamicArray
в scanf()
(, который читает ввод и сохраняет результат в заданном месте ), это приводит к неопределенному поведению 2) , потому что ваш Программа в конечном итоге обращается к недействительной памяти.
Когда вы передаете &dynamicArray
в printf()
с указателем формата %s
, printf()
, он получает доступ к этому адресу для записи строки символов и в итоге получает доступ к недопустимой памяти, что приводит к неопределенному поведению 2) . Следовательно, вы получаете segfault.
1) Массив автоматически преобразуется в указатель на свой первый элемент, но есть несколько исключений из этого правила (Стандарты C11 # 6.3.2.1p3):
- Массив является операндом оператора
sizeof
. - Массив является операндом оператора
_Alignof
. - Массив является операндом
&
. - Массив - это строковый литерал, используемый для инициализации массива.
2) неопределенное поведение включает в себя его некорректное выполнение (либо сбой, либо генерирование без вывода сообщений) неверные результаты), или он, к счастью, может делать именно то, что и хотел программист