c++ c arrays pointers comma-operator

c++ - sizeof tomando dos argumentos



arrays pointers (7)

Como varios ya han dicho, y quiero agregar solo una cosa, sizeof es un operador que toma una expresión o una expresión moldeada. Por esta razón, tomé el hábito de escribir la parátesis a un tamaño de solo si es una expresión moldeada.

char *arr; struct xxx { ... } v;

Escribiré

sizeof arr sizeof v

pero

sizeof (struct xxx) /* Note the space after the sizeof, it''s important */ sizeof (char *)

Hago lo mismo con return no paréntesis, ya que no es una llamada a función, y si pongo paréntesis es porque la expresión siguiente los necesita.

En C.1.3 del C ++ IS (2003. Está también en C ++ 11 IS), el estándar señala una diferencia entre ISO C y C ++; a saber, para

char arr[100];

sizeof(0, arr) devuelve sizeof(char*) en C, pero 100 en C ++.

No puedo encontrar documentación para sizeof tomando dos argumentos. La alternativa obvia es el operador de coma, pero no lo creo: sizeof(arr) en C es 100 ; sizeof(0, arr) es sizeof(char*) . Tanto sizeof(0, arr) como sizeof(arr) son 100 en C ++.

Puede que me esté perdiendo todo el punto del IS en este contexto. ¿Alguien puede ayudar? Esto es similar a una pregunta discutida en el ''09, pero nadie se refirió al IS, y no creo que se haya dado la respuesta correcta.

Editar : en realidad, el IS está hablando del operador de coma. Por lo tanto, por algún motivo (0, arr) devuelve un char* en C, pero un char[100] en C ++. ¿Por qué?


En C, el operador de coma no produce un lvalor, por lo tanto, la matriz arr que es un lvalue decae en un tipo de puntero que es un valor r (en este caso). Entonces sizeof(0,arr) convierte en equivalente a sizeof(char*) , debido a la conversión de lvalue a rvalue .

Pero en C ++, el operador de coma produce un valor l. No hay conversión lvalue-to-rvalue . Entonces sizeof(0,arr) permanece igual, lo que es equivalente a sizeof(char[100]) .

Por cierto, sizeof no es una función, es un operador. Entonces el siguiente es C ++ completamente válido (y C, si imaginas printf lugar de cout ):

int a[100], b[200], c[300], d[400]; cout << sizeof(a,b,c,d) << endl;

Demostración: http://www.ideone.com/CtEhn

Puede pensar que he pasado 4 operandos a sizeof pero eso es incorrecto. sizeof opera sobre el resultado de los operadores de coma. Y es debido a los muchos operadores de coma que ven muchos operandos.

4 operandos con 3 operadores de coma; al igual que en 1+2+3+4 , hay 3 operadores, 4 operandos.

Lo anterior es equivalente a lo siguiente (válido en C ++ 0x):

auto & result = (a,b,c,d); //first all comma operators operate on the operands. cout << sizeof (result) << endl; //sizeof operates on the result

Demostración: http://www.ideone.com/07VNf

Entonces, es el operador de coma el que te hace sentir que hay muchos argumentos . Aquí la coma es un operador, pero en la llamada de función, la coma NO es un operador, simplemente es un separador de argumento.

function(a,b,c,d); //here comma acts a separator, not operator.

Entonces sizeof(a,b,c,d) opera en el tipo de resultado de , operadores, exactamente de la misma manera, sizeof(1+2+3+4) opera en el tipo de resultado de + operadores.

También tenga en cuenta que no puede escribir sizeof(int, char, short) , precisamente porque el operador de coma no puede operar en los tipos . Funciona solo con valor . Creo que sizeof es el único operador en C y C ++, que también puede operar en tipos . En C ++, hay un operador más que puede operar en tipos . Su nombre es typeid .


En C, la matriz se está desintegrando a un puntero, debido a la diferente especificación del operador de coma en relación con los valores r y l (no es el único lugar donde se puede encontrar tal diferencia). En C ++, la matriz permanece como una matriz, produciendo el resultado correcto.


Es un operador de coma. Y la diferencia de la que estás hablando no tiene absolutamente nada que ver con sizeof . La diferencia está realmente en el valor de lvalue-a-rvalue, matriz-a-puntero y comportamientos de decaimiento similares entre los lenguajes C y C ++.

En este sentido, el lenguaje C es bastante desencadenante: las matrices decaen a punteros prácticamente de forma inmediata (con la excepción de muy pocos contextos específicos), por lo que el resultado de 0, arr expresión 0, arr tiene char * . Es equivalente a 0, (char *) arr .

En el lenguaje C ++, las matrices conservan su "variedad" mucho más tiempo. Cuando se utilizan en el contexto de , matrices de operador no se degradan en punteros (y los valores l no decaen en valores r), por lo que en C ++ el tipo de 0, arr expresión 0, arr aún es char[100] .

Esto es lo que explica la diferencia en el sizeof comportamiento en ese ejemplo. ?: operador es otro ejemplo de un operador que demuestra la diferencia similar en el comportamiento de desintegración, es decir, sizeof(0 ? arr : arr) le dará diferentes resultados en C y C ++. Básicamente, todo se debe al hecho de que los operadores C normalmente no conservan la validez de sus operandos. Se pueden usar muchos operadores para demostrar este comportamiento.


Esto no es tomar dos argumentos. sizeof es un operador, no una función.

Considere que (0, arr) es una expresión que usa el operador de coma, y ​​todo lo demás encaja.


La mejor manera de ver qué podría estar pasando aquí es mirar la gramática en el estándar. Si miramos el borrador de la sección estándar C99 6.5.3 Operadores unarios, párrafo 1 , podemos ver que la gramática para sizeof es:

sizeof unary-expression sizeof ( type-name )

Entonces, el segundo no se aplica, pero ¿cómo se aplica el sizeof unary-expression en este caso? Si miramos la sección A.2.1 Expresiones del borrador del estándar y trabajamos a través de la gramática de la siguiente manera:

unary-expression -> postfix-expression -> primary-expression -> ( expression )

obtenemos los paréntesis alrededor de una expresión y ahora solo tenemos que mirar la gramática para el operador de coma de la sección 6.5.17 Operador de coma y vemos:

expression: assignment-expression expression , assignment-expression

Entonces ahora tenemos:

sizeof( expression , assignment-expression ) ^ | comma operator

Tanto la expresión como la expresión de asignación pueden llevarnos a la expresión primaria que tiene la siguiente gramática:

primary-expression: identifier constant string-literal ( expression )

y 0 es una constante y arr es un identificador por lo que tenemos:

sizeof( constant , identifier )

Entonces, ¿qué hace el operador de coma aquí? La sección 6.5.17 párrafo 2 dice:

El operando izquierdo de un operador de coma se evalúa como una expresión vacía; hay un punto de secuencia después de su evaluación. Entonces se evalúa el operando correcto; el resultado tiene su tipo y valor. 97)

dado que el operador de coma no es una de las excepciones donde una matriz no se convierte en un puntero genera un puntero ( esto se trata en la sección 6.3.2.1 Valores L, matrices y designadores de funciones ), lo que significa que terminamos con:

sizeof( char * )

En C ++ la gramática es bastante similar, así que terminamos en el mismo lugar, pero los operadores de coma funcionan de manera diferente. El operador de coma Comandante 5.18 sección estándar de C ++ dice:

[...] El tipo y el valor del resultado son el tipo y el valor del operando correcto; el resultado es de la misma categoría de valor que su operando derecho [...]

por lo tanto, no es necesaria la conversión de matriz a puntero, por lo que terminamos con:

sizeof( char[100] )


sizeof no toma dos argumentos. Pero tampoco es una función, por lo que (...) no delimitan los argumentos de función, solo son una parte opcional de la sintaxis y hacen cumplir la agrupación. Cuando escribe sizeof(0, arr) , el argumento de sizeof es la expresión única 0, arr . Una sola expresión con un operador de coma, que evalúa la expresión a la izquierda de la coma, arroja su valor (pero no sus efectos secundarios), luego evalúa la expresión a la derecha de la coma y usa su valor como el valor de la expresión completa.

No estoy seguro acerca de C, pero esto podría ser una diferencia entre los lenguajes. En C ++, la conversión de matriz a puntero no ocurre a menos que sea necesaria; en C, si mal no recuerdo, el estándar dice que siempre se lleva a cabo, excepto en ciertos contextos. Incluyendo como el operador de sizeof . En este caso, dado que el operador de coma no tiene restricciones con respecto a los tipos de sus operandos, la conversión de matriz a puntero no tiene lugar en C ++. En C, una operación del operador de coma no aparece en las excepciones, por lo que la conversión de matriz a puntaje tiene lugar. (En este caso, la matriz es un operando del operador de coma, y ​​no del sizeof ).