Перебора аргументов функции с помощью указателя на первый

Я хотел бы знать, придерживается ли следующий код 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 даже не упоминает стек,все, что она указывает, это правила области.


стандарт не поддерживает. Это очень неприлично.

индексирование массива и арифметика указателя действительны только для массивов. (Обратите внимание на небольшое исключение: вы можете читать указатель один мимо массива или скаляра, но вы не можете уважение его.)