В C не является ошибкой приведение указателя от одного типа к другому. Однако хороший компилятор выдаст предупреждение при передаче неверного типа указателя в функцию без явного приведения. Если вы не получаете предупреждение, я настоятельно рекомендую проверить настройки вашего компилятора, чтобы убедиться, что предупреждения включены. Или рассмотрите возможность использования другого компилятора. ; -)
Чтобы понять, почему это работает, вам нужно немного понять язык ассемблера и то, как C использует стек для передачи параметров. Вы можете визуализировать стопку как большую стопку пластин, где каждая пластина содержит одну простую переменную. На многих платформах все параметры передаются в стеке. func
нажмет y
и x
, вызовет f
, а затем сбросит переменные обратно. valid
загружает x
и y
, просматривая две верхние записи в стеке. invalid
находит x
, просматривая верхнюю запись в стеке.
Вот как может выглядеть стек внутри недействительного:
main: 3
uninitialized
f: 2
1
invalid
invalid: 2
1
invalid()
принимает один параметр, поэтому он просто смотрит на вершину стека (1) и загружает его как параметр.
Так же работают такие функции, как printf
. Они могут принимать переменное количество параметров. Первый параметр находится на вершине стека, и они могут просто смотреть вниз по стеку, чтобы найти столько параметров, сколько им нужно. Некоторые системы передают некоторые параметры в регистры вместо использования стека, но он работает аналогично.
В самые ранние времена C объявления функций вообще не включали параметры. На самом деле, если вы объявляете функцию без чего-либо между скобками, вы все равно можете определить функцию таким образом. Например, это прекрасно компилируется:
void foo();
void bar(void) {
foo(5); /* foo's parameters are implicit */
}
Вот почему важно включать void
при объявлении функции без параметров. Он сообщает компилятору, что функция действительно принимает параметры no . В скобках ничего нет, это функция с неявными параметрами.