Перебора аргументов функции с помощью указателя на первый
Я хотел бы знать, придерживается ли следующий код C стандарта C99 и / или C11:
void foo(int bar0, int bar1, int bar2) {
int *bars = &bar0;
printf("0: %dn1: %dn2: %dn", bars[0], bars[1], bars[2]);
}
int main(int argc, char **argv) {
foo(8, 32, 4);
return 0;
}
этот фрагмент кода компилируется и запускается, как ожидалось, при использовании visual studio 2013 и печатает:
0: 8
1: 32
2: 4
3 ответов
нет, не где-нибудь поблизости.
Стандарт С ++ не гарантирует, что аргументы функции хранятся в последовательных ячейках памяти (или, любой конкретный заказ, если на то пошло). Это зависит от компилятора и / или платформы (архитектура), чтобы решить, как аргументы функции передаются в функцию.
чтобы добавить некоторую ясность, нет даже гарантии, что аргументы, которые должны быть переданы, хранятся в памяти (например,, стека), вообще. Они также могут использовать аппаратные регистры (при необходимости), для некоторых или все параметры, чтобы сделать операции быстро. Например,
-
PowerPC
архитектура PowerPC имеет большое количество регистров, поэтому большинство функций могут передавать все аргументы в регистрах для одноуровневых вызовов. [...]
-
MIPS
в наиболее часто используемым соглашением о вызовах для 32-битных MIPS является O32 ABI, который передает первые четыре аргумента функции в регистрах
$a0
-$a3
; последующие аргументы передаются в стек. [...] -
X86
архитектура x86 используется со многими различными соглашениями о вызовах. Из-за небольшого количества архитектурных регистров соглашения о вызовах x86 в основном передают Аргументы в стеке, а возвращаемое значение (или указатель на него) передается в регистр.
и так далее. Проверьте Полная статья wiki здесь.
Итак, в вашем случае,bars[0]
это действительный открыть, но будет ли bars[1]
и bars[2]
действительны, зависит от основного окружающая среда (платформа/компилятор), полностью. Лучше не полагаться на поведение, которого вы ожидаете.
это сказал, просто придурок, в случае, если вы не собираетесь использовать аргументы (если) передал main()
, вы можете просто уменьшить подпись int main(void) {
.
нет оно не придерживается к любому опубликованному стандарту. Как хранить Аргументы и локальные переменные, и где, зависит от компилятора. То, что может работать в одном компиляторе, может не работать в другом или даже в другой версии того же компилятора.
спецификация C даже не упоминает стек,все, что она указывает, это правила области.
стандарт не поддерживает. Это очень неприлично.
индексирование массива и арифметика указателя действительны только для массивов. (Обратите внимание на небольшое исключение: вы можете читать указатель один мимо массива или скаляра, но вы не можете уважение его.)