Я прочитал многие предыдущие сообщения на C4700, но я не могу найти решение моей проблемы.
У меня есть небольшой скрипт, написанный для демонстрации указателей на структуру:
struct foo
{
int * bar;
};
#include<iostream>
using namespace std;
int main()
{
foo * fooptr;
int * num;
*num = 25;
*fooptr->bar = *num;
cout << "now fooptr points to a foo struct whose bar points to: " << *fooptr->bar;
fooptr->bar = num;
cout <<"now fooptr struct bar shares memory address with num at " <<num;
return 0;
}
Когда я его компилирую, я получаю два предупреждения C4700 для неинициализированных локальных переменных num и fooptr. Я пошел вперед и инициализировал оба значения до NULL, поэтому ошибка компилятора исчезла, но не удивительно, что я получил исключение:
Необработанное исключение в 0x00265DF7 в файле test.exe: 0xC0000005: место записи нарушения доступа 0x00000000.
Видите ли, я всегда думал, что, когда я не инициализирую эти указатели, они будут автоматически инициализированы случайными адресами (так же, как неинициализированные ints/chars/doubles будут назначены мусора) --so не так ли будет здесь?
Если инициализация в этом случае действительно необходима (почему?), То есть ли простой способ решения этой проблемы?
Неинициализированные переменные не инициализируются случайными значениями, они не инициализируются. На уровне машинного кода они имеют любое значение, когда они были созданы. Это может быть или не быть адресом фактического объекта. В любом случае, это неопределенное поведение, чтобы попытаться получить доступ к неинициализированному значению указателя, как если бы был объект по этому адресу.
Таким образом, ваш компилятор делает вам одолжение, выдавая предупреждение (это не требуется), потому что ваш код имеет неопределенное поведение.
то есть ли легкое обходное решение этой проблемы?
Установите свои указатели для указания на действительные объекты перед их разыменованием. Если вы этого не сделаете, тогда нет никаких обещаний о том, какое поведение будет иметь ваша программа.
*fooptr->bar
, вы ссылаетесь на bar
. То есть вы пытаетесь получить int, на который указывает bar
. Но bar
ничего не указывает, потому что вы никогда не инициализировали его. Вам нужно что-то вроде этого: fooptr->bar = new int;
, После этого вы можете делать любые из перечисленных вами вещей.
Вместо
int *num; // num points to somewhere random
*num = 25; // writing somewhere random makes zero sense
// and if your OS allowed you to do it, you would
// crash your computer very often.
вы должны написать
int num = 25;
int *pnum = # // pnum is a pointer to int which has been
// initialized with the address of num
И то же самое относится к содержимому struct
.
C4700 не является ошибкой. DOT. Но MSVC не скомпилируется на C4700, что является ошибкой, потому что переключатель компилятора "/sdl" включен по умолчанию для C4700 на сайте visualstudio, переключатель MSDN/sdl для vs 2012+