Указатель на литеральное значение

Машины для подсчета голосов не являются открытым исходным кодом, потому что лоббисты для "электрический, пока" промышленность успешно не обманула политиков, не квалифицированных для совершения технологического выбора в покупку их нефти змеи. Это было выполнено с соединением anti-FOSS FUD и старое доброе сформированный взяточничество забастовка> взносы в пользу избирательной кампании.

Обновление: я попытаюсь отправить ссылки здесь время от времени, что шоу, как поставщики отвечают на критическое исследование. Не стесняйтесь добавлять свое собственное. (Pro-OSS– только: "человек" может сделать свое собственное сообщение!)

16
задан James 14 October 2009 в 07:09
поделиться

9 ответов

В C89 нет возможности сделать это напрямую. Вам придется использовать набор макросов для создания такого выражения.

В C99 разрешено объявлять литералы struct-or-union, а инициализаторы скаляров могут быть написаны с использованием аналогичного синтаксиса. Поэтому есть один способ добиться желаемого эффекта:

#include <stdio.h>

void f(const int *i) {
    printf("%i\n", *i);
}

int main(void) {
    f(&(int){1});
    return 0;
}
30
ответ дан 30 November 2019 в 15:41
поделиться

Я понимаю, что вы здесь пытаетесь сделать, но вы пытаетесь использовать здесь две принципиально разные вещи. Суть вопроса в том, что операторы case должны использовать значения, которые присутствуют во время компиляции , но указатели на данные в памяти доступны только во время выполнения .

Когда вы делаете это:

#define THIS_CONST 'A'
char c = THIS_CONST;
write(fd, &c, sizeof(c))

вы делаете две вещи. Вы делаете макрос THIS_CONST доступным для остальной части кода во время компиляции, и вы создаете новый char во время выполнения, который инициализируется этим значением. В момент, когда выполняется строка write (fd, & c, sizeof (c)) , концепция THIS_CONST больше не существует, поэтому вы правильно определили, что можете создать указатель на c , статическая константа char THIS_CONST = 'A'; switch (c) { case THIS_CONST: // ошибка - метка case не сводится к целочисленной константе ... }

вы пишете код, в котором значение оператора case необходимо оценить во время компиляции. Однако в этом случае вы указали THIS_CONST таким образом, что это переменная, и поэтому его значение доступно только во время выполнения , несмотря на то, что вы «знаете», что он будет иметь конкретную значение . Конечно, другие языки допускают разные вещи с операторами case, но таковы правила для C.

Вот что я бы посоветовал:

1) Не вызывайте переменную THIS_CONST . Нет никаких технических причин не делать этого, но соглашение предполагает, что это макрос во время компиляции, и вы не хотите вводить в заблуждение своих читателей.

2) Если вы хотите, чтобы одни и те же значения были доступны во время компиляции и выполнения, найти подходящий способ сопоставления макросов времени компиляции с переменными времени выполнения. Это может быть очень просто:

#define CONST_STAR '*'
#define CONST_NEWLINE '\n'

static const char c_star CONST_STAR;
static const char c_newline CONST_NEWLINE;

Тогда вы можете сделать:

switch(c) {
  case CONST_STAR:
    ...
    write(fd, &c_star, sizeof(c_star))
    ...
}

(Обратите внимание, что sizeof (char) всегда единица, Возможно, вы это уже знаете, но это не так широко, как должно бы быть.)

0
ответ дан 30 November 2019 в 15:41
поделиться

Для символов вы можете использовать дополнительные глобальные статические переменные. Может быть, что-то вроде:

#define THIS_CONST 'a'
static char tmp;
#define PTR_TO(X) ((tmp = X),&tmp)

write(fd,PTR_TO(THIS_CONST),sizeof(char));
1
ответ дан 30 November 2019 в 15:41
поделиться

There's no reason the compiler has to put the literal into any memory location, so your question doesn't make sense. For example a statement like

int a;
a = 10;

would probably just be directly translated into "put a value ten into a register". In the assembly language output of the compiler, the value ten itself never even exists as something in memory which could be pointed at, except as part of the actual program text.

You can't take a pointer to it.

If you really want a macro to get a pointer,

#include <stdio.h>
static char getapointer[1];

#define GETAPOINTER(x)  &getapointer, getapointer[0] = x

int main ()
{
    printf ("%d\n",GETAPOINTER('A'));
}
0
ответ дан 30 November 2019 в 15:41
поделиться
#define THIS_CONST 'a'

Это просто макрос. Компилятор просто вставляет "a" везде, где вы используете THIS_CONST. Вы можете попробовать:

const char THIS_CONST = 'a';

Но я подозреваю, что это не сработает (у меня нет под рукой c-компилятора, чтобы опробовать его, а с тех пор, как я писал c-код, прошло уже довольно много лет).

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

C просто не допускает адресации символьных литералов, таких как 'A'. Как бы то ни было, тип символьных литералов в C - int (char в C ++, но этот вопрос помечен как C). «A» будет иметь значение, определяемое реализацией (например, 65 в системах ASCII). Взятие адреса значения бессмысленно и невозможно.

Теперь, конечно, вы можете взять адрес других видов литералов, таких как строковые литералы, например, следующее хорошо:

write(fd, "potato", sizeof "potato");

Это потому, что строковый литерал "potato" является массивом, а его значение - указатель на 'p' в начале.

Чтобы уточнить / пояснить, вы можете использовать только адрес объектов. то есть для оператора & (адрес-из) требуется объект, а не значение.

И чтобы ответить на другой вопрос, который я пропустил, C не требует '

4
ответ дан 30 November 2019 в 15:41
поделиться

Хорошо, я придумал кое-что для хака, только для символов - но я ' Я помещу его сюда, чтобы увидеть, вдохновит ли он кого-нибудь на какие-либо лучшие решения

static const char *charptr(char c) {
    static char val[UCHAR_MAX + 1];
    val[(unsigned char)c] = c;
    return &val[(unsigned char)c];
}

...

write(fd, charptr(THIS_CONST), sizeof(char));
-2
ответ дан 30 November 2019 в 15:41
поделиться

Поскольку вызов функции write () для записи одного символа в файловый дескриптор почти наверняка снижает производительность, вы, вероятно, захотите просто выполнить fputc (THIS_CONST, stream).

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

Единственный способ получить указатель - это поместить литерал в переменную (ваш первый пример кода). Затем вы можете использовать переменную с write () и литерал в switch .

5
ответ дан 30 November 2019 в 15:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: