c++ - owns - runescape classic
extern en línea (5)
Creo que malinterpretas __FILE__ y __LINE__ según esta afirmación:
porque utiliza las macros __FILE__ y __LINE__ que deberían resolverse para la persona que llama, pero no esta función llamada
Hay varias fases de compilación, y el preproceso es el primero. __FILE__ y __LINE__ se reemplazan durante esa fase. Entonces, para cuando el compilador pueda considerar la función de inline, ya han sido reemplazados.
Entiendo que "en línea" en sí mismo es una sugerencia para el compilador, y en su descreción puede o no alinear la función, y también producirá código de objeto enlazable.
Creo que "static inline" hace lo mismo (puede o no alinearse) pero no produce código de objeto enlazable cuando está inline (ya que ningún otro módulo podría enlazarse a él).
¿Dónde encaja "extern en línea" en la imagen?
Supongamos que quiero reemplazar una macro de preprocesador por una función en línea y requiero que esta función quede en línea (por ejemplo, porque usa las macros __FILE__ y __LINE__ que deberían resolverse para la persona que llama pero no para esta función llamada). Es decir, quiero ver un compilador o un error de enlazador en caso de que la función no se inserte. ¿"Extern inline" hace esto? (Supongo que, si no lo hace, no hay forma de lograr este comportamiento más que quedarse con una macro).
¿Hay diferencias entre C ++ y C?
¿Hay diferencias entre los diferentes proveedores y versiones del compilador?
La situación en línea, estática en línea y en línea externa es complicada, sobre todo porque gcc y C99 definen significados ligeramente diferentes para su comportamiento (y presumiblemente C ++, también). Puede encontrar información útil y detallada sobre lo que hacen en C here .
Las macros son su elección aquí en lugar de las funciones en línea. Una rara ocasión donde las macros gobiernan sobre las funciones en línea. Prueba lo siguiente: ¡escribí este código "MACRO MAGIC" y debería funcionar! Probado en gcc / g ++ Ubuntu 10.04
//(c) 2012 enthusiasticgeek (LOGGING example for )
#ifdef __cplusplus
#include <cstdio>
#include <cstring>
#else
#include <stdio.h>
#include <string.h>
#endif
//=========== MACRO MAGIC BEGINS ============
//Trim full file path
#define __SFILE__ (strrchr(__FILE__,''/'') ? strrchr(__FILE__,''/'')+1 : __FILE__ )
#define STRINGIFY_N(x) #x
#define TOSTRING_N(x) STRINGIFY_N(x)
#define _LINE (TOSTRING_N(__LINE__))
#define LOG(x, s...) printf("(%s:%s:%s)" x "/n" , __SFILE__, __func__, _LINE, ## s);
//=========== MACRO MAGIC ENDS ============
int main (int argc, char** argv) {
LOG("Greetings ! - from enthusiasticgeek/n");
return 0;
}
Para múltiples archivos, defina estas macros en un archivo de encabezado separado que incluya lo mismo en cada archivo c / cc / cxx / cpp. Por favor, prefiera las funciones en línea o los identificadores de const (según lo exija el caso) sobre las macros siempre que sea posible.
Parece que estás tratando de escribir algo como esto:
inline void printLocation()
{
cout <<"You''re at " __FILE__ ", line number" __LINE__;
}
{
...
printLocation();
...
printLocation();
...
printLocation();
y esperando que obtenga diferentes valores impresos cada vez. Como dice Don, no lo hará, porque __FILE__ y __LINE__ son implementados por el preprocesador, pero el compilador implementa inline. Entonces, desde donde llame a printLocation, obtendrá el mismo resultado.
La única forma en que puede hacer que esto funcione es hacer que printLocation sea una macro. (Sí, lo sé...)
#define PRINT_LOCATION {cout <<"You''re at " __FILE__ ", line number" __LINE__}
...
PRINT_LOCATION;
...
PRINT_LOCATION;
...
en K & R C o C89, en línea no era parte del idioma. Muchos compiladores lo implementaron como una extensión, pero no había una semántica definida con respecto a cómo funcionaba. GCC fue uno de los primeros en implementar inline
e introdujo las construcciones extern inline
inline
, static inline
y extern inline
; la mayoría de los compiladores anteriores a C99 generalmente siguen su ejemplo.
GNU89:
-
inline
: la función puede estar en línea (sin embargo, es solo una pista). Una versión fuera de línea siempre se emite y es visible externamente. Por lo tanto, solo puede tener dicha línea en línea definida en una unidad de compilación, y cualquier otra necesita verla como una función fuera de línea (o obtendrá símbolos duplicados en el momento del enlace). -
extern inline
no generará una versión fuera de línea, pero podría llamar a uno (que, por lo tanto, debe definir en alguna otra unidad de compilación. Sin embargo, se aplica la regla de una definición; la versión fuera de línea debe tener el mismo código). como el en línea ofrecido aquí, en caso de que el compilador lo llame en su lugar. -
static inline
no generará una versión fuera de línea visible externamente, aunque podría generar un archivo estático. La regla de una sola definición no se aplica, ya que nunca hay un símbolo externo emitido ni una llamada a uno.
C99 (o GNU99):
-
inline
: como GNU89 "extern inline"; no se emite ninguna función visible externamente, pero se podría llamar a uno y, por lo tanto, debe existir -
extern inline
: como GNU89 "inline": se emite un código externo visible, por lo que a lo sumo una unidad de traducción puede usar esto. -
static inline
: como GNU89 "estática en línea". Este es el único portátil entre gnu89 y c99
C ++:
Una función que está en línea en cualquier lugar debe estar en línea en todas partes, con la misma definición. El compilador / enlazador clasificará varias instancias del símbolo. No hay una definición de static inline
o extern inline
, aunque muchos compiladores los tienen (generalmente siguiendo el modelo gnu89).