Файл 1.c
int a[10];
Файл main.c:
extern int *a;
int main()
{
printf("%d\n", a[0]);
return 0;
}
Дает мне segfault! Что не так?
Файл 1.c
int a[10];
Файл main.c:
extern int *a;
int main()
{
printf("%d\n", a[0]);
return 0;
}
Дает мне segfault! Что не так?
Массивы разлагаются или неявно преобразуются в указатели при передаче функции в качестве аргумента или при преобразовании в значение r в правой части оператора присваивания. Так что-то вроде:
int array[10];
int* a = array; //implicit conversion to pointer to type int
void function(int* a);
function(array); //implicit conversion to pointer to type int
работает просто отлично. Но не означает, что массивы сами по себе являются указателями. Поэтому, если вы обрабатываете массив, как указатель, как вы это делали, вы фактически рассматриваете тип массива как-бы если он был указателем, который содержал адрес для объекта int
. Поскольку ваш массив на самом деле представляет собой последовательность объектов int
, а не указывает на объекты int
, вы фактически пытаетесь разыменовать какое-то место в памяти, которое не указывает ни на что иное (т.е. Первый слот в array
представляет собой числовое целочисленное значение, подобное 0
, которое будет похоже на разыменование NULL). Вот почему вы преуспеваете. Обратите внимание, что если вы сделали что-то вроде этого:
int array[] = { 1, 2, 3, 4, 5};
int b = *array;
Это все еще работает, поскольку array
снова неявно преобразуется в указатель на блок памяти, который удерживает последовательность целых значений и затем разыменовывается, чтобы получить значение в первой последовательности. Но в вашем случае, объявив ваш массив текущему модулю кода как внешне определенному указателю, а не массиву, он пропустит неявное преобразование в указатель, который обычно выполняется, и просто используйте объект массива as-if были указателем на сам объект, а не на массив объектов.
Хорошо объяснено в часто задаваемых вопросах > . И есть продолжение. Изображение во втором звене стоит миллион долларов.
char a[] = "hello";
char *p = "world";
Короткий ответ: использовать extern int a[]
.
Немного позднее, дубликат этой проблемы был только что введен (и закрыт). В ответах здесь не упоминаются файлы заголовков...
Проблема будет поймана во время компиляции, если вы поместите объявление массива a
в заголовочный файл, где он принадлежит, вместо того, чтобы помещать его в файл .c. Затем заголовочный файл должен быть включен в оба файла .c, и компилятор может видеть, что то, что вы заявили, неверно.
Ваш заголовочный файл будет содержать:
extern int myarray[];
Вы получите что-то вроде "error: conflicting types for a
", если вместо этого укажете a
как указатель.
В основном вам нужно написать свой main.c следующим образом:
extern int a[];
int main()
{
printf("%d\n", a[0]);
return 0;
}
Проверьте вывод следующего кода.
file1.c
#include <stdio.h>
extern int* my_arr;
void my_print()
{
printf("%d", my_arr);
}
main.c
#include <stdio.h>
int my_arr[2] = {1,2};
extern void my_print();
void main()
{
my_print();
}
Выход
1
внутри File1.c my_arr - это указательная переменная, которая имеет значение 1. означает, что ему был присвоен 1-й элемент my_arr []. Затем, если вы используете * my_arr для доступа к ячейке памяти ox1, вы получаете ошибку seg, потому что вам не разрешено обращаться к ox01.
Почему указатель my_arr был назначен 1 (первый элемент my_arr [])?
Имеет отношение к тому, как работает ассемблер. Прочитайте в этой статье
Почему ваш код не может получить доступ к 0x01?
Я знаю, что это связано с операционной системой, не позволяющей доступу к адресному пространству по коду пользователя. Это все, что я знаю. google, если вы хотите получить дополнительную информацию.