В последний раз названный параметром не функция или массив?

Старые версии Ubuntu могут быть найдены здесь .

Вот ссылка на 10.04 .

16
задан Lightness Races with Monica 12 November 2011 в 23:04
поделиться

4 ответа

Ограничение для параметров регистров или параметров функций, вероятно, выглядит примерно так:

  • вам не разрешено принимать адрес переменной с классом хранения регистр .
  • указатели на функции иногда сильно отличаются от указателей на объекты. Например, они могут быть больше, чем указатели на объекты (вы не можете надежно преобразовать указатель функции в указатель объекта и обратно), поэтому добавление некоторого фиксированного числа к адресу указателя функции может не привести вас к следующему параметру . Если va_start () и / или va_arg () были реализованы путем добавления некоторой фиксированной суммы к адресу paramN и указатели функций были больше, чем указатели объектов, расчет приведет к неправильному адресу для объекта , который возвращает va_arg () . Может показаться, что это не лучший способ реализовать эти макросы, но могут быть платформы, которые имеют (или даже нуждаются) в этом типе реализации.

Я не могу придумать, в чем проблема может заключаться в предотвращении разрешения параметров массива , но PJ Plauger говорит об этом в своей книге «Стандартная библиотека C»:

Некоторые ограничения, наложенные на макросы, определенные в , кажутся излишне жесткими. Для некоторых реализаций они есть. Однако каждый был представлен чтобы удовлетворить потребности хотя бы одной серьезной реализации C.

И я полагаю, что мало кто знает о тонкостях библиотеки C больше, чем Plauger. Я надеюсь, что кто-то сможет ответить на этот конкретный вопрос на реальном примере; Я думаю, это будет интересная мелочь.

Новая информация:


"Обоснование международного стандарта - Языки программирования - C" говорит о va_start () :

аргумент parmN для va_start был предназначен для помощи разработчикам, пишущим определение соответствующего макроса va_start полностью на C, даже с использованием компиляторов до C89 (например, путем взятия адреса параметра). Ограничения на объявление параметра parmN вытекают из намерения разрешить этот вид реализации, поскольку применение оператора & к имени параметра может не дать желаемого результата, если объявление параметра не соответствует этим ограничениям. .

Не то, чтобы это помогло мне с ограничением параметров массива.

6
ответ дан 30 November 2019 в 23:00
поделиться

Это не неопределенно. Имейте в виду, что когда параметр объявлен как int paramN [] , фактический тип параметра все равно немедленно изменится на int * paramN (что видно в C ++, например, если вы примените typeid к paramN ).

Я должен признать, что я не уверен, для чего вообще нужен этот бит в спецификации, учитывая, что у вас не может быть параметров функции или массива типы в первую очередь (поскольку они будут распадаться по указателю).

3
ответ дан 30 November 2019 в 23:00
поделиться

I found another relevant quote, from Dinkumware.

The last parameter must not have register storage class, and it must have a type that is not changed by the translator. It cannot have:

* an array type
* a function type
* type float
* any integer type that changes when promoted
* a reference type [C++ only]

So apparently, the problem is precisely that the parameter gets passed in a way different from how it is declared. Interestingly enough, they also ban float and short, even though those should be supported by the standard.

As a hypothesis, it could be that some compilers have problems doing sizeof correctly on such parameters. E.g. it might be that, for

int f(int x[10])
{
        return sizeof(x);
}

some (buggy) compiler will return 10*sizeof(int), thus breaking the va_start implementation.

2
ответ дан 30 November 2019 в 23:00
поделиться

Я могу только догадываться, что ограничение регистр предназначено для упрощения реализации библиотеки / компилятора - это устраняет особый случай, о котором им следует беспокоиться.

Но я понятия не имею об ограничении массива / функции. Если бы это было только в стандарте C ++, я бы рискнул предположить, что существует некий неясный сценарий сопоставления шаблонов, в котором разница между параметром типа T [] и типа T * имеет значение, правильная обработка которого усложнила бы va_start и т. д. Но поскольку этот пункт также присутствует в стандарте C, очевидно, что такое объяснение исключено.

Мой вывод: упущение в стандартах. Возможный сценарий: некоторый предстандартный компилятор C реализовал параметры типа T [] и T * по-разному, и представитель этого компилятора в комитете по стандартам C добавил к стандарту вышеуказанные ограничения; этот компилятор позже устарел, но никто не считал, что ограничения достаточно убедительны, чтобы обновить стандарт.

1
ответ дан 30 November 2019 в 23:00
поделиться