что компилятор делает со [мной], который является массивом? И что, если указателя?

Мне сказали c-часто-задаваемые-вопросы, что компилятор делает разные вещи для контакта со [мной] в то время как массива или указателя. Вот пример от c-часто-задаваемых-вопросов:

char a[] = "hello";
char *p = "world";

Учитывая объявления выше, когда компилятор видит выражение a [3], он испускает код, чтобы запуститься в местоположении, переместить три прошлое это и выбрать символ там. То, когда это видит выражение p [3], это испускает код, чтобы запуститься в местоположении ''p'', выбрать значение указателя там, добавить три к указателю и наконец выбрать символ, указало.

Но мне сказали, что при контакте со [мной], компилятор имеет тенденцию преобразовывать (который является массивом) к указателю на массив. Таким образом, я хочу видеть ассемблерные коды для обнаружения, который является правильным.

Править:

Вот источник этого оператора. c-часто-задаваемые-вопросы И примечание это предложение:

выражение формы [я] заставляет массив затухать в указатель, после правила выше, и затем преобразовываться в нижний индекс, как была бы переменная указателя в выражении p [я] (хотя возможные доступы памяти будут отличаться,"

Я довольно смущен этого: так как затух к указателю, тогда почему он имеет в виду о "доступах памяти, будет отличаться?"

Вот мой код:

// array.cpp
#include 
using namespace std;

int main()
{
    char a[6] = "hello";
    char *p = "world";
    printf("%c\n", a[3]);
    printf("%c\n", p[3]);
}

И вот часть ассемблерного кода, я получил использование g ++-S array.cpp

    .file   "array.cpp" 
    .section    .rodata
.LC0:
    .string "world"
.LC1:
    .string "%c\n"
    .text
.globl main
    .type   main, @function
main:
.LFB2:
    leal    4(%esp), %ecx
.LCFI0:
    andl    $-16, %esp
    pushl   -4(%ecx)
.LCFI1:
    pushl   %ebp
.LCFI2:
    movl    %esp, %ebp
.LCFI3:
    pushl   %ecx
.LCFI4:
    subl    $36, %esp
.LCFI5:
    movl    $1819043176, -14(%ebp)
    movw    $111, -10(%ebp)
    movl    $.LC0, -8(%ebp)
    movzbl  -11(%ebp), %eax
    movsbl  %al,%eax
    movl    %eax, 4(%esp)
    movl    $.LC1, (%esp)
    call    printf
    movl    -8(%ebp), %eax
    addl    $3, %eax
    movzbl  (%eax), %eax
    movsbl  %al,%eax
    movl    %eax, 4(%esp)
    movl    $.LC1, (%esp)
    call    printf
    movl    $0, %eax
    addl    $36, %esp
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret 

Я не могу выяснить механизм [3] и p[3] от кодов выше. Такой как:

  • где был "привет" инициализирован?
  • что 1 819 043 176$ означает? возможно, это - адрес памяти "привет" (адрес a)?
  • Я уверен, что "-11 (%ebp)" означает [3], но почему?
  • В "movl-8 (%ebp), %eax", содержание poniter p хранится в EAX, правильно? Так $.LC0 означает содержание указателя p?
  • Что делает "movsbl %al, %eax" средний?
  • И, отметьте эти 3 строки кодов:
    movl 1 819 043 176$,-14 (%ebp)
    movw 111$,-10 (%ebp)
    $ movl.LC0,-8 (%ebp)

    Последний использует "movl", но почему он не перезаписывал содержание-10 (%ebp)? (Я знаю anser теперь:), адрес является возрастающим, и "movl $.LC0 - 8 (%ebp) только перезапишет {-8,-7,-6,-5} (%ebp)),

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

Большое спасибо за Вашу справку.

14
задан ibread 15 January 2010 в 18:40
поделиться

3 ответа

Blazeds - это библиотека с открытым исходным кодом, созданная Adobe. Вы можете использовать его, чтобы позвонить в Java Services (методы) непосредственно из стороны Flex, без необходимости создавать некоторые веб-сервисы. Есть также другие преимущества, такие как обмен сообщениями, но главное - это тот факт, что упрощает интеграцию Flex / Java.

Интеграция пружины Blazeds - это проект, созданный ребятами Springsource, чтобы использовать файлы конфигурации пружины для настроек Blazeds и для использования модели Spring Programming. Поэтому, если вы используете пружину на стороне подачи и прогибайте на стороне клиента, это очень хорошая идея, чтобы добавить взвешенные и использовать интеграцию пружины / взвешенные.

-121--4482091-

A является указателем на массив символов. P - это указатель на чар, который происходит, в данном случае, указанным на строку-литерате.

movl    $1819043176, -14(%ebp)
movw    $111, -10(%ebp)

Инициализирует локальный «привет» на стеке (поэтому он ссылается через EBP ). Поскольку в «Hello» более 4BYTES требуется два инструкции.

movzbl  -11(%ebp), %eax
movsbl  %al,%eax

Ссылки A [3] : процесс двухэтапного процесса из-за ограничения с точки зрения доступа к памяти, на который ссылаются EBP (мой x86-FU немного ржавый) Отказ

MOVL-8 (% EBP),% EAX действительно имеет значение P P указатель.

LC0 Ссылки на «относительную память» местоположение: фиксированное местоположение памяти будет выделено после загрузки программы в память.

MOVSBL% AL,% EAX означает: «Переместить один байт, снизить» (дать или взять ... Я должен был посмотреть ... Я немного ржавый на этом фронте). AL представляет собой байт из реестра EAX .

5
ответ дан 1 December 2019 в 15:01
поделиться

Я бы предпочел подход к прямому доступу к частным переменным. IMHO методы gettter увеличивают беспорядок.

-121--4167149-

BlazeDS - библиотека с открытым исходным кодом, созданная Adobe. Его можно использовать для вызова сервисов (методов) Java непосредственно со стороны Flex без создания некоторых веб-сервисов. Есть и другие преимущества, такие как обмен сообщениями, но главное, что значительно упрощает интеграцию Flex/Java.

Интеграция Spring BlazeDS - это проект, созданный парнями SpringSource для использования файлов конфигурации Spring для настроек BlazeDS и для использования модели программирования Spring. Поэтому при использовании Spring на стороне обслуживания и Flex на стороне клиента рекомендуется добавить BlazeDS и использовать интеграцию Spring/BlazeDS.

-121--4482091-

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

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

Принципиальное различие между указателем и массивами заключается в том, что массив по существу является опорным. Если допустимо инициализировать указатель на значение null или изменить значение, которое хранит указатель, массивы не могут быть null и не могут быть установлены в другие массивы; они являются по существу постоянными указателями, которым нельзя присвоить значение null.

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

2
ответ дан 1 December 2019 в 15:01
поделиться

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

Обратите внимание на это предложение: «Выражение формы A [I] вызывает массив в распаду Указатель, следующий за правилом выше, а затем должен быть подписан так же, как было бы переменную указателя в выражении P [I] (хотя возможная память будет отличаться, - я довольно запутался в этом: поскольку Чтобы указать, тогда почему он означает о «доступах к памяти, будет отличаться?

Это связано с тем, что после того, как распадается, доступ равен для (теперь значения указателя), а также указатель. Но разница Как Это значение указателя попадает в первую очередь. Давайте посмотрим на пример:

char c[1];

char cc;
char *pc = &cc;

Теперь у вас есть массив. Этот массив не принимает никакого хранения, кроме одного CHARK! Есть Ни один указатель не хранится для него. И у вас есть указатель, который указывает на символ. Указатель принимает размер одного адреса, и у вас есть один символ, который E указатель указывает на. Теперь давайте посмотрим, что произойдет для корпуса массива, чтобы получить значение указателя:

c[0] = 'A';
// #1: equivalent: *(c + 0) = 'A';
// #2: => 'c' appears not in address-of or sizeof 
// #3: => get address of "c": This is the pointer value P1

Корпус указателя отличается:

pc[0] = 'A';
// #1: equivalent: *(pc + 0) = 'A';
// #2: => pointer value is stored in 'pc'
// #3: => thus: read address stored in 'pc': This is the pointer value P1

, как вы видите, для корпуса массива для получения требуемого значения указателя, где мы добавляем значение индекса ( В этом случае скучно 0 ), нам не нужно читать из памяти, потому что адрес массива уже требуется значение указателя. Но для корпуса указателя нам нужен значение указателя, сохраняется в указатере: нам нужен один читал из памяти, чтобы получить этот адрес.

После этого путь равен для обоих:

// #4: add "0 * sizeof(char)" to P1. This is the address P2
// #5: store 'A' to address P2

вот код ассемблера, сгенерированный для массива, и чехол указателя:

        add     $2, $0, 65  ; write 65 into r2
        stb     $2, $0, c   ; store r2 into address of c
# pointer case follows
        ldw     $3, $0, pc  ; load value stored in pc into r3
        add     $2, $0, 65  ; write 65 into r2
        stb     $2, $3, 0   ; store r2 into address loaded to r3

мы можем просто хранить 65 (ASCII для «A» ) по адресу C C (который будет известен уже при компиляции или сочетании времени, когда он является глобальным). Для корпуса указателя мы сначала придется загрузить адрес, хранящийся в нем в регистр 3 , а затем напишите 65 на этот адрес.

4
ответ дан 1 December 2019 в 15:01
поделиться