Почему не включают указатели?

Например:

#include <stdio.h>

void why_cant_we_switch_him(void *ptr)
{
    switch (ptr) {
        case NULL:
            printf("NULL!\n");
            break;
        default:
            printf("%p!\n", ptr);
            break;
    }
}

int main(void)
{
    void *foo = "toast";
    why_cant_we_switch_him(foo);
    return 0;
}

gcc test.c -o test
test.c: In function 'why_cant_we_switch_him':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values

Просто любопытный. Действительно ли это - техническое ограничение?

Править

Люди, кажется, думают, что существует только одно постоянное выражение указателя. Это, действительно верно, хотя? Например, вот общая парадигма в Objective C (это действительно только C кроме NSString, id и nil, которые являются просто указателями, таким образом, это все еще релевантно — я просто хотел указать, что существует, на самом деле, общее использование для него, несмотря на этот являющийся только техническим вопросом):

#include <stdio.h>
#include <Foundation/Foundation.h>

static NSString * const kMyConstantObject = @"Foo";

void why_cant_we_switch_him(id ptr)
{
    switch (ptr) {
        case kMyConstantObject: // (Note that we are comparing pointers, not string values.)
            printf("We found him!\n");
            break;
        case nil:
            printf("He appears to be nil (or NULL, whichever you prefer).\n");
            break;
        default:
            printf("%p!\n", ptr);
            break;
    }
}

int main(void)
{
    NSString *foo = @"toast";
    why_cant_we_switch_him(foo);
    foo = kMyConstantObject;
    why_cant_we_switch_him(foo);

    return 0;
}

gcc test.c -o test -framework Foundation
test.c: In function 'why_cant_we_switch_him':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values

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

28
задан Michael 4 September 2013 в 15:37
поделиться

9 ответов

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

9
ответ дан 28 November 2019 в 03:20
поделиться

Поскольку существует только одно постоянное указательное выражение

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

13
ответ дан 28 November 2019 в 03:20
поделиться

Переключатель сравнивает переменную с набором констант времени компиляции. Кроме null, я не вижу ни одной допустимой константы времени компиляции, с которой можно было бы сравнить указатель. Например:

switch (ptr) { 
   case &var1: printf ("Pointing to var1"); break;
   case &var2: printf ("Pointing to var2"); break;
}

var1 и var2, вероятно, различны в каждом запуске программы и не являются константами времени компиляции. Одна из возможностей может заключаться в том, что это адреса портов, отображаемых в память, которые всегда фиксированы, но в противном случае я не вижу, как вы можете легко расширить это из ваших двух случаев (null / not-null).

8
ответ дан 28 November 2019 в 03:20
поделиться

Примечания на будущее (после большой головной боли из-за всего этого): 1. если вы получили сообщение об ошибке рукопожатия - файл pem, который вы создали, вероятно, неправильный.

а. убедитесь, что файл находится в том же каталоге, что и php, который вы пытаетесь запустить. b. export certificate p12 file AND ключ под ним в утилите доступа к keychain both этих файлов будет ОДИНАКОВОГО размера, но они ОТЛИЧАЮТСЯ. c. выполните вышеуказанные команды «openssl» в терминале macintosh.

  1. в настоящее время все, что я могу сделать, это запустить php как sudo, из-за 400 chmod для ck.pem. что-то должно дать...

btw, сообщение «Failed to enable crypto» (Не удалось включить шифрование) будет отображаться при правильной работе системы.

-121--3461188-

Phirehose определенно путь:

http://code.google.com/p/phirehose/

-121--1918706-

switch операторы работают только на интегральных выражениях. Указатель не является интегральным выражением.

При желании можно явно преобразовать указатель в интегральный тип, но предлагаемый код немного странный и неестественный.

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

8
ответ дан 28 November 2019 в 03:20
поделиться

Приведите ptr к int и попробуйте снова:

switch( (int)ptr )

или, если быть более корректным:

switch( (intptr_t)ptr ) // C99 integer type to hold a pointer
7
ответ дан 28 November 2019 в 03:20
поделиться

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

- (void)drawRect:(CGRect)rect
{
    // get the contect
    CGContextRef context = UIGraphicsGetCurrentContext();

    //now draw the rounded rectangle
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
    CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 0.0);

    //since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame
    CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30);
    CGFloat radius = 45;
    // the rest is pretty much copied from Apples example
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect);

    {
        //for the shadow, save the state then draw the shadow
        CGContextSaveGState(context);

        // Start at 1
        CGContextMoveToPoint(context, minx, midy);
        // Add an arc through 2 to 3
        CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
        // Add an arc through 4 to 5
        CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
        // Add an arc through 6 to 7
        CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
        // Add an arc through 8 to 9
        CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
        // Close the path
        CGContextClosePath(context);

        CGContextSetShadow(context, CGSizeMake(4,-5), 10);
        CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);

        // Fill & stroke the path
        CGContextDrawPath(context, kCGPathFillStroke);

        //for the shadow
        CGContextRestoreGState(context);
    }

    {
        // Start at 1
        CGContextMoveToPoint(context, minx, midy);
        // Add an arc through 2 to 3
        CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
        // Add an arc through 4 to 5
        CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
        // Add an arc through 6 to 7
        CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
        // Add an arc through 8 to 9
        CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
        // Close the path
        CGContextClosePath(context);

        CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);
        CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);       

        // Fill & stroke the path
        CGContextDrawPath(context, kCGPathFillStroke);
    }
}
-121--1510784-

Добавьте его в начало сценария:

use Carp 'verbose';
$SIG{ __DIE__ } = sub { Carp::confess( @_ ) };

Он создаст трассировку стека для всех неустранимых ошибок.

Метки -121--2628351-

case ожидают константное выражение, обычно целое число, и указатели имеют тенденцию плохо сравниваться с ними, за исключением случая NULL. Вы можете бросить intptr_t, но это все еще бессмысленно, когда у вас есть только одна вещь, с которой вы можете сравнить. Операторы

switch существуют, поскольку компилятор часто может превратить их в таблицу переходов , что является концепцией, которая лучше всего подходит, если метки вариантов являются последовательными целыми числами. Но в случае указателя, приведенного к интегральному типу, вы ничего не получаете над , если / else с помощью переключателя, за исключением более громоздкого синтаксиса.

2
ответ дан 28 November 2019 в 03:20
поделиться

Вы можете (если вам действительно нужно). Просто приведите указатель к целому числу соответствующего размера. Для этого следует использовать intptr_t. Это не значит, что я рекомендую это делать, но у вас могут быть свои причины.

#include <stdint.h>
#include <stdio.h>

void we_can_switch_him(void *ptr)
{
    switch ((intptr_t)ptr) {
        case (intptr_t)NULL:
            printf("NULL!\n");
            break;
        default:
            printf("%p!\n", ptr);
            break;
    }
}

int main(void)
{
    void *foo = "toast";
    we_can_switch_him(foo);
    return 0;
}
4
ответ дан 28 November 2019 в 03:20
поделиться

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

1
ответ дан 28 November 2019 в 03:20
поделиться

Ух! зачем вообще использовать оператор switch? Операторы switch следует использовать только в том случае, если у вас есть 3 или более вариантов на выбор, если у вас есть 2 варианта, тогда используйте оператор if () {} else {}.

Джошуа, это незаконное использование указателя в коммутаторе.

Если вам действительно необходимо использовать оператор switch, приведите его к _int64, long long или некоторому целочисленному типу, размер которого гарантированно будет равен или больше указателя (зависит от компилятора).

Также некоторые компиляторы могут ограничивать максимальный размер переключателя значением int или другим произвольным размером. в этом случае вы вообще не можете использовать оператор switch.

Округ Колумбия

-1
ответ дан 28 November 2019 в 03:20
поделиться
Другие вопросы по тегам:

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