Скажите пожалуйста , как просмотреть оптимизированый код после прохождения компилятором , перед основной компиляцией…
Спасибо
подпишусь
С чего ты решил, что такой код есть?
Много раз встречал , как некоторые мастера описывали проблемы кода связанные с тем , что компилятор оптимизирует некоторый код на свое усмотрение . например если стандартная переменная обьявлена не как volatile , но при этом используется в коде с условием , но не изменяется в нем , то компилятор может решить ее исключить (раз она все равно не принимает значение нужное в условии) При этом они писали ,
… запустите компилятор и просмотрите листинг кода сформированный компилятором после оптимизации , как видите компилятор при первом прохождении исключает эту переменную т.к думает…
к сожалению они упускают то, что не все знают как его посмотреть …
вот либо перед компиляцией, либо после компиляции
Код после компиляции не имеет ничего общего с исходным текстом. Это программа в машинных кодах. Вы уверены, что что-нибудь разберете там?
Начните с ответа на вопрос, знаете ли вы ассемблер.
В том то и дело . они иммеют ввиду не код после компиляции в кодах , а именно код оптимизированый …
сhar str[125];
for(size_t i = 0; i < strlen(str); i++)
{
...
}
код в скетче
сhar str[125];
size_t length = strlen(str);
for(size_t i = 0; i < lenght; i++)
{
...
}
код после оптимизации перед компиляцией
Покажите хоть одну ссылку на такое обсуждение, где бы обсуждался именно ОПТИМИЗИРОВАННЫЙ КОМПИЛЯТОРОМ код.
Сколько видел таких дискуссий - всегда берут код ПОСЛЕ КОМПИЛЯЦИИ и дизассембоируют его.
Бред какой-то написал. Где тут оптимизация? Это фундаментально другой код.
https://habr.com/ru/post/673428/
ну например … правда здесь он не говорит давайте посмотрим… постараюсь и те найти но как то не думал , что это проблема
правда возможно я не правильно понял и они иммели ввиду действительно дизассемблированный код , но явно это не указывалось… поэтому и возник вопрос
а зря не думали.
Вы обознались. Никакого кода после оптимизации никто не обсуждает, потому что компилятор не создает никакого промежуточного кода “после оптимизации”, он сразу компилирует его в машинный код.
То, что вы хотите посмотреть - просто не существует .
Разницу между volatile и нет в принципе нельзя увидеть на высокуровневом языке. Он не оперирует регистрами процессора. И тот факт, что в статье они не упомянуты, говорит о том, что статья дилетантская.
Понял. спасибо вопрос снят
Прочел.
Абсолютно бестолковая статья. Какой-то новичок долго не мог понять, зачем нужно volatile. Потом ему показалось, что понял, и он решил осчастливить мир своим открытием.
Дело в том, что оптимизация включает много аспектов.
- часть из них может быть выполнена как до, так и после компиляции (аппаратно независимая оптимизация),
- часть - только после (аппаратно зависимая оптимизация),
- часть - вообще неподвластна компилятору (ее должен выполнять человек).
Т.е. теоретически мог бы существовать вариант:
- Аппаратно независимая оптимизация,
- Компиляция.
- Аппаратно зависимая оптимизация.
Сразу отмечу, что даже в этом случае после этапа 1 мы получим неполную оптимизацию.
Но главное даже не в этом.
Мне кажется вполне очевидным, что разработчики оптимизирующего компилятора позаботятся и о том, чтобы сам компилятор работал оптимально. Т.е. по возможности быстрее. (т.е. проведут ту самую “человеческую” оптимизацию).
И тут сразу появляются два обстоятельства:
- Компьютеру “легче” (а, следовательно, - быстрее) работать с бинарными данными, чем с текстовыми. Следовательно, даже аппаратно независимую оптимизацию оптимальнее делать после компиляции, а не до.
- Каждый проход компиляции сопровождается чтением исходных данных с диска и записью на диск результатов работы. А дисковые операции - довольно медленная штука. Зачастую именно они и занимают бОльшую часть времени. Следовательно нужно стремиться к минимизации количества проходов.
Отсюда приходим единственно возможному варианту:
- Компиляция.
- Оптимизация.
Таким образом в результате простейших рассуждений приходим к выводу: варианта “после оптимизации, но до компиляции” существовать не может ввиду того, что этапы компиляции и оптимизации производятся в обратном порядке.
а я тут побаловался на linux, т е если ТС дружит с командной строкой GCC и может откомпилировать Arduino код, то почему бы ему не вытащить код после препроцессора и ассемблерный код - пусть наслаждается/разбирается.
Спойлер
# 1 "ftp2cl.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "ftp2cl.cpp"
# 1 "/usr/include/string.h" 1 3 4
# 26 "/usr/include/string.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 1 3 4
# 33 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 461 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 452 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 453 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/long-double.h" 1 3 4
# 454 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 462 "/usr/include/features.h" 2 3 4
# 485 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 486 "/usr/include/features.h" 2 3 4
# 34 "/usr/include/x86_64-linux-gnu/bits/libc-header-start.h" 2 3 4
# 27 "/usr/include/string.h" 2 3 4
# 28 "/usr/include/string.h" 3 4
extern "C" {
# 1 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" 1 3 4
# 209 "/usr/lib/gcc/x86_64-linux-gnu/10/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/string.h" 2 3 4
# 43 "/usr/include/string.h" 3 4
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
size_t __n) throw () __attribute__ ((__nonnull__ (1, 2)));
extern void *memmove (void *__dest, const void *__src, size_t __n)
throw () __attribute__ ((__nonnull__ (1, 2)));
extern void *memccpy (void *__restrict __dest, const void *__restrict __src,
int __c, size_t __n)
throw () __attribute__ ((__nonnull__ (1, 2)));
extern void *memset (void *__s, int __c, size_t __n) throw () __attribute__ ((__nonnull__ (1)));
extern int memcmp (const void *__s1, const void *__s2, size_t __n)
throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern "C++"
{
extern void *memchr (void *__s, int __c, size_t __n)
throw () __asm ("memchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern const void *memchr (const void *__s, int __c, size_t __n)
throw () __asm ("memchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 89 "/usr/include/string.h" 3 4
}
# 99 "/usr/include/string.h" 3 4
extern "C++" void *rawmemchr (void *__s, int __c)
throw () __asm ("rawmemchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern "C++" const void *rawmemchr (const void *__s, int __c)
throw () __asm ("rawmemchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern "C++" void *memrchr (void *__s, int __c, size_t __n)
throw () __asm ("memrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern "C++" const void *memrchr (const void *__s, int __c, size_t __n)
throw () __asm ("memrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 122 "/usr/include/string.h" 3 4
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
throw () __attribute__ ((__nonnull__ (1, 2)));
extern char *strncpy (char *__restrict __dest,
const char *__restrict __src, size_t __n)
throw () __attribute__ ((__nonnull__ (1, 2)));
extern char *strcat (char *__restrict __dest, const char *__restrict __src)
throw () __attribute__ ((__nonnull__ (1, 2)));
extern char *strncat (char *__restrict __dest, const char *__restrict __src,
size_t __n) throw () __attribute__ ((__nonnull__ (1, 2)));
extern int strcmp (const char *__s1, const char *__s2)
throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern int strncmp (const char *__s1, const char *__s2, size_t __n)
throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern int strcoll (const char *__s1, const char *__s2)
throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern size_t strxfrm (char *__restrict __dest,
const char *__restrict __src, size_t __n)
throw () __attribute__ ((__nonnull__ (2)));
# 1 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" 1 3 4
# 22 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" 1 3 4
# 28 "/usr/include/x86_64-linux-gnu/bits/types/__locale_t.h" 3 4
struct __locale_struct
{
struct __locale_data *__locales[13];
const unsigned short int *__ctype_b;
const int *__ctype_tolower;
const int *__ctype_toupper;
const char *__names[13];
};
typedef struct __locale_struct *__locale_t;
# 23 "/usr/include/x86_64-linux-gnu/bits/types/locale_t.h" 2 3 4
typedef __locale_t locale_t;
# 154 "/usr/include/string.h" 2 3 4
extern int strcoll_l (const char *__s1, const char *__s2, locale_t __l)
throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2, 3)));
extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,
locale_t __l) throw () __attribute__ ((__nonnull__ (2, 4)));
extern char *strdup (const char *__s)
throw () __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1)));
extern char *strndup (const char *__string, size_t __n)
throw () __attribute__ ((__malloc__)) __attribute__ ((__nonnull__ (1)));
# 204 "/usr/include/string.h" 3 4
extern "C++"
{
extern char *strchr (char *__s, int __c)
throw () __asm ("strchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern const char *strchr (const char *__s, int __c)
throw () __asm ("strchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 224 "/usr/include/string.h" 3 4
}
extern "C++"
{
extern char *strrchr (char *__s, int __c)
throw () __asm ("strrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern const char *strrchr (const char *__s, int __c)
throw () __asm ("strrchr") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 251 "/usr/include/string.h" 3 4
}
# 261 "/usr/include/string.h" 3 4
extern "C++" char *strchrnul (char *__s, int __c)
throw () __asm ("strchrnul") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
extern "C++" const char *strchrnul (const char *__s, int __c)
throw () __asm ("strchrnul") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
# 273 "/usr/include/string.h" 3 4
extern size_t strcspn (const char *__s, const char *__reject)
throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern size_t strspn (const char *__s, const char *__accept)
throw () __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern "C++"
{
extern char *strpbrk (char *__s, const char *__accept)
throw () __asm ("strpbrk") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
extern const char *strpbrk (const char *__s, const char *__accept)
throw () __asm ("strpbrk") __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1, 2)));
# 301 "/usr/include/string.h" 3 4
}
Спойлер
.file "ftp2cl.cpp"
.text
.section .rodata
.align 4
.type _ZL34_cat_ftp_client_max_size_char_user, @object
.size _ZL34_cat_ftp_client_max_size_char_user, 4
_ZL34_cat_ftp_client_max_size_char_user:
.long 32
.align 4
.type _ZL33_cat_ftp_client_max_size_temp_buf, @object
.size _ZL33_cat_ftp_client_max_size_temp_buf, 4
_ZL33_cat_ftp_client_max_size_temp_buf:
.long 512
.align 4
.type _ZL28_cat_ftp_client_max_recv_buf, @object
.size _ZL28_cat_ftp_client_max_recv_buf, 4
_ZL28_cat_ftp_client_max_recv_buf:
.long 1024
.LC0:
.string "MDTM"
.LC1:
.string "213 "
.text
.align 2
.globl _ZN12CatFTPclient11getFileDateEPcS0_
.type _ZN12CatFTPclient11getFileDateEPcS0_, @function
_ZN12CatFTPclient11getFileDateEPcS0_:
.LFB15:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $544, %rsp
movq %rdi, -520(%rbp)
movq %rsi, -528(%rbp)
movq %rdx, -536(%rbp)
movq -520(%rbp), %rax
movzbl 82(%rax), %eax
testb %al, %al
je .L2
leaq -512(%rbp), %rax
movl $1297368141, (%rax)
movw $32, 4(%rax)
movq -528(%rbp), %rdx
leaq -512(%rbp), %rax
movq %rdx, %rsi
movq %rax, %rdi
call strcat@PLT
leaq -512(%rbp), %rax
movq %rax, %rdi
call strlen@PLT
Эти два кода не эквивалентны и ни один оптимизатор никогда не преобразует первый код во второй.
Кода на С++ “после оптимизации” в природе не существует, он не появляется ни на каком этапе.
Можно посмотреть код после препроцессора, если интересно. Я иногда смотрю. С ардуино IDE он появляется безо всяких танцев с бубнами в папке build.
Ну хотя бы после препроцессора … только вот папки build не нашел … у меня ide 2 версии
смотрел везде и в скрытых/системных тоже
с GCC не вышло … c иде его нет, а пакеты win-avr и avr-gcc с ошибкой . первый ругается на сам код, а второй на отсутствие файлов… пока не разобрался еще что хотят
В папке temp не смотрел? (cd %temp%)