Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

231
Visualizações
clang/gcc no puede establecer variables globales en una constante de dirección menos otra constante de dirección

El siguiente programa compila sin errores.

 #include <stdio.h> char addr_a[8]; char addr_b[8]; unsigned long my_addr = (unsigned long)addr_b - 8; // PASS // unsigned long my_addr = (unsigned long)addr_b - (unsigned long)addr_a; // FAIL (error: initializer element is not constant) int main() { printf("%lx\n", my_addr); return 0; }

Curiosamente, cuando configuro unsigned long my_addr = (unsigned long)addr_b - (unsigned long)addr_a el compilador arroja "error: el elemento inicializador no es constante".

Sé que los globales solo se pueden inicializar con una expresión constante. También sé que los tipos de expresiones constantes que se pueden usar en un inicializador para un global se especifican en la sección 6.6p7 del estándar C :

Se permite más libertad para expresiones constantes en inicializadores. Dicha expresión constante será, o se evaluará como, una de las siguientes:

  • una expresión constante aritmética,
  • una constante de puntero nulo,
  • una constante de dirección, o
  • una constante de dirección para un tipo de objeto completo más o menos una expresión de constante entera.

Tenga en cuenta que se permite una constante de dirección menos una constante entera, pero no una constante de dirección menos otra constante de dirección.

Pregunta:

¿Por qué el estándar C restringe las formas en que puede inicializar variables globales? ¿Qué impide que el estándar C acepte unsigned long my_addr = (unsigned long)addr_b - (unsigned long)addr_a ?

Por qué querrías esto?

Supongamos addr_a y addr_b representan el inicio y el final de la sección .text respectivamente. Un programa puede querer mapear la sección .text , que tiene tamaño (unsigned long)addr_b - (unsigned long)addr_a . El proyecto trustware-firmware-a hace esto en la etapa 2 del cargador de arranque (BL2). Consulte BL_CODE_END - BL_CODE_BASE , que se utiliza en arm_bl2_setup.c .

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Los objetos con duración de almacenamiento estático (es decir, globales, más locales definidos como static ) solo se pueden inicializar con una expresión constante .

Los tipos de expresiones constantes que se pueden usar en un inicializador para dicho objeto se especifican en la sección 6.6p7 del estándar C :

Se permite más libertad para expresiones constantes en inicializadores. Dicha expresión constante será, o se evaluará como, una de las siguientes:

  • una expresión constante aritmética,
  • una constante de puntero nulo,
  • una constante de dirección, o
  • una constante de dirección para un tipo de objeto completo más o menos una expresión de constante entera.

Tenga en cuenta que se permite una constante de dirección más una constante entera, pero no una constante de dirección más otra constante de dirección.

De acuerdo, esto todavía no es exactamente lo que tiene, ya que tiene constantes de dirección convertidas en tipo entero. Así que revisemos 6.6p6 que define una expresión constante entera :

Una expresión de constante entera tendrá un tipo entero y solo tendrá operandos que sean constantes enteras, constantes de enumeración, constantes de caracteres, expresiones sizeof cuyos resultados sean constantes enteras, expresiones _Alignof y constantes flotantes que sean los operandos inmediatos de las conversiones. Los operadores de conversión en una expresión constante entera solo convertirán tipos aritméticos en tipos enteros , excepto como parte de un operando en el operador sizeof o _Alignof .

Este párrafo no permite convertir una dirección constante a un tipo entero como parte de una expresión constante entera, pero aparentemente esto parece ser compatible como una extensión.

over 4 years ago · Santiago Trujillo Relatório

0

¿Qué impide que el estándar C acepte my_addr largo sin firmar = (largo sin firmar)addr_a + (largo sin firmar)addr_b?

La razón subyacente es "¿Por qué alguien querría eso?" No tiene sentido agregar dos direcciones absolutas juntas; el resultado no es la dirección de nada en particular.

Por lo tanto, es una especie de cosa del huevo y la gallina. El lenguaje no lo admite porque es inútil, pero también porque los enlazadores existentes y los formatos de archivos de objetos no admiten dicha reubicación. Por ejemplo, para ELF en x86-64, consulte la Tabla 4.9 de psABI para obtener una lista de las reubicaciones admitidas y tenga en cuenta que no hay S+S . Y los enlazadores no lo admiten porque es inútil y porque el idioma no requiere que sea compatible.

Supongo que originalmente, las herramientas probablemente llegaron antes que el lenguaje (los primeros compiladores de C habrían usado enlazadores diseñados para programas de ensamblaje). Entonces, las herramientas originales probablemente no eran compatibles con esto, el lenguaje no vio la necesidad de exigir que lo hicieran y, con el tiempo, ninguno vio la necesidad de agregarlo.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda