초기화되지 않은 로컬 변수가 가장 빠른 난수 생성기입니까?
초기화되지 않은 로컬 변수가 정의되지 않은 동작(UB)이라는 것을 알고 있습니다.또, 그 값은 트랩 표현을 가지고 있을 가능성이 있기 때문에, 향후의 조작에 영향을 주는 경우가 있습니다만, 때때로 랜덤 번호를 시각적인 표현에만 사용하고 싶기 때문에, 예를 들면, 프로그램의 다른 부분에서는 랜덤한 색으로 시각적인 효과를 설정하는 등, 그 외의 부분에서는 사용하지 않습니다.예를 들어 다음과 같습니다.
void updateEffect(){
for(int i=0;i<1000;i++){
int r;
int g;
int b;
star[i].setColor(r%255,g%255,b%255);
bool isVisible;
star[i].setVisible(isVisible);
}
}
그렇게 빠른가요?
void updateEffect(){
for(int i=0;i<1000;i++){
star[i].setColor(rand()%255,rand()%255,rand()%255);
star[i].setVisible(rand()%2==0?true:false);
}
}
그리고 다른 난수 발생기보다 빠르죠?
분명히 말씀드리지만, 저희 프로그램에서는 정의되지 않은 행동을 일으키지 않습니다.그건 절대 좋은 생각이 아니야, 임마.이 규칙에는 드문 예외가 있습니다. 예를 들어, Offset of을 구현하는 라이브러리 구현자인 경우입니다.만약 당신의 경우가 그러한 예외에 해당한다면 당신은 이미 이것을 알고 있을 것입니다.이 경우 초기화되지 않은 자동변수를 사용하는 것은 정의되지 않은 동작임을 알 수 있습니다.
컴파일러는 정의되지 않은 동작에 대한 최적화에 매우 적극적으로 대응하고 있으며 정의되지 않은 동작이 보안 결함을 초래하는 많은 사례를 발견할 수 있습니다.가장 악명 높은 경우는 아마도 C++ 컴파일 버그에 대한 답변에서 언급한 Linux 커널 늘 포인터 체크 삭제일 것입니다.여기서 정의되지 않은 동작에 대한 컴파일러 최적화는 유한 루프를 무한 루프로 변화시킨다.
CERT의 「위험한 최적화와 인과 관계의 상실」(비디오)을 읽어 보면, 다음과 같은 것이 있습니다.
C 및 C++ 프로그래밍 언어에서 정의되지 않은 동작을 이용하여 최적화를 개선하는 컴파일러 라이터가 증가하고 있습니다.
이러한 최적화는 종종 개발자가 소스 코드에 대한 원인-효과 분석, 즉 이전 결과에 대한 다운스트림 결과의 의존성을 분석하는 기능을 방해합니다.
따라서 이러한 최적화는 소프트웨어의 인과관계를 제거하고 소프트웨어 장애, 결함 및 취약성의 확률을 높이고 있습니다.
특히, 불확정치에 관해서는, C표준 결함 리포트 451:미초기화 자동 변수의 불안정성은, 몇개의 흥미로운 읽기를 가능하게 한다.아직 해결되지 않았지만 흔들리는 값의 개념을 도입했습니다.이것은 값의 불확정성이 프로그램을 통해 전파될 수 있고 프로그램의 다른 지점에서 다른 불확정 값을 가질 수 있다는 것을 의미합니다.
나는 이런 일이 일어나는 어떤 예도 모르지만 이 시점에서 우리는 그것을 배제할 수 없다.
실제 예시로 예상한 결과가 아니다
랜덤 값을 얻을 가능성은 거의 없습니다.컴파일러는 루프를 완전히 없앨 수 있습니다.예를 들어, 다음과 같은 간단한 대소문자가 있습니다.
void updateEffect(int arr[20]){
for(int i=0;i<20;i++){
int r ;
arr[i] = r ;
}
}
updateEffect(int*): # @updateEffect(int*)
retq
또는 다음과 같이 모든 0을 얻을 수 있습니다.
void updateEffect(int arr[20]){
for(int i=0;i<20;i++){
int r ;
arr[i] = r%255 ;
}
}
updateEffect(int*): # @updateEffect(int*)
xorps %xmm0, %xmm0
movups %xmm0, 64(%rdi)
movups %xmm0, 48(%rdi)
movups %xmm0, 32(%rdi)
movups %xmm0, 16(%rdi)
movups %xmm0, (%rdi)
retq
이 두 경우 모두 완전히 허용 가능한 형태의 정의되지 않은 행동입니다.
참고로 Itanium을 사용하는 경우 트랩 값이 다음과 같이 될 수 있습니다.
[...] 레지스터에 특별한 not-a-thing 값이 있는 경우 몇 가지 지시사항을 제외하고 레지스터 트랩을 읽습니다[...]
기타 중요한 주의사항
UB Canaries 프로젝트에서 지적된 gcc와 clang의 차이는 초기화되지 않은 메모리에 대해 정의되지 않은 동작을 얼마나 활용할 것인지에 대한 것입니다.이 기사에는 다음과 같은 내용이 기재되어 있습니다(강조합니다.
물론 컴파일러의 프로바이더가 UB를 이용하려고 하지 않거나 아직 이용하지 않았기 때문에 언어 표준이나 특정 컴파일러가 수행하는 모든 것과 전혀 관계가 없다는 것을 스스로 분명히 할 필요가 있습니다.컴파일러 프로바이더로부터의 진정한 보증이 존재하지 않는 경우, 우리는 아직 이용되지 않은 UB는 시한폭탄이라고 말하고 싶다.즉, 컴파일러가 조금 더 공격적이 되는 다음 달이나 내년에 종료되기를 기다리고 있다.
Mattheu M.가 지적했듯이, 정의되지 않은 행동에 대해 모든 C 프로그래머가 알아야 할 것 #2/3도 이 질문과 관련이 있습니다.다른 것들 중에서 다음과 같이 말하고 있다(나의 강조:
중요한 것은 정의되지 않은 동작에 기초한 최적화는 미래에 언제든지 버그가 있는 코드로 트리거될 수 있다는 것입니다.인라인화, 루프 언롤링, 메모리 프로모션 및 기타 최적화는 계속 개선될 것입니다.이러한 이유의 상당 부분은 위와 같은 2차 최적화를 공개하는 것입니다.
컴파일러는 필연적으로 비난을 받게 되고, C코드의 거대한 몸체는 폭발을 기다리는 지뢰이기 때문에, 이것은 나에게 매우 불만스러운 일입니다.
완전성을 위해 구현에서는 정의되지 않은 동작을 적절하게 정의하도록 선택할 수 있습니다.예를 들어 gcc는 결합을 통해 유형 펀닝을 허용하는 반면 C++에서는 정의되지 않은 동작처럼 보입니다.이 경우 실장에서는 문서화할 필요가 있으며, 일반적으로는 휴대할 수 없습니다.
다른 사용자가 지적했듯이 이것은 Undefined Behavior(UB; 정의되지 않은 동작)입니다.
실제로는 효과가 있을 것이다.x86 [-64]아키텍처의 초기화되지 않은 레지스터에서 읽으면 가비지 결과가 실제로 생성되며, (예를 들어 다음과 같이) 나쁜 일은 일어나지 않습니다.Itanium: 레지스터가 무효로 플래그가 지정되므로 NaN과 같은 오류를 읽을 수 있습니다).
다만, 다음의 2개의 주된 문제가 있습니다.
특별히 무작위적인 건 아닐 거예요.이 경우 스택에서 읽고 있기 때문에 이전에 있었던 모든 것을 얻을 수 있습니다.10분 전에 입력한 비밀번호나 할머니의 쿠키 레시피 같은 것들이죠
이런 것들이 당신의 코드에 스며들게 하는 것은 나쁜 습관이다.엄밀히 말하면 컴파일러는
reformat_hdd();
정의되지 않은 변수를 읽을 때마다 표시됩니다.그럴 일은 없겠지만, 어쨌든 하면 안 돼요.위험한 짓은 하지 마세요.예외가 적을수록 항상 우발적인 실수로부터 안전해집니다.
UB의 더 시급한 문제는 프로그램 전체의 동작을 정의하지 못한다는 것입니다.최신 컴파일러는 이를 사용하여 방대한 양의 코드를 제거하거나 과거로 되돌릴 수 있습니다.UB를 가지고 노는 것은 빅토리아 시대의 엔지니어가 원자로를 해체하는 것과 같습니다.잘못될 것이 무수히 많으며, 기본 원칙이나 구현 기술의 절반도 모를 것입니다.괜찮겠지만 그래도 그렇게 놔두면 안 돼자세한 내용은 다른 좋은 답변을 참조하십시오.
그리고 널 해고할 거야
아니, 끔찍해.
초기화되지 않은 변수를 사용하는 동작은 C와 C++ 모두에서 정의되지 않으며, 이러한 스킴이 바람직한 통계 속성을 가질 가능성은 매우 낮다.
"빠르고 더러운" 난수 생성기를 원하는 경우rand()
최선의 선택이야구현에서는 곱셈, 덧셈 및 계수만 수행합니다.
제가 아는 가장 빠른 발전기는uint32_t
의사 변환 변수의 유형으로I
, 및 사용
I = 1664525 * I + 1013904223
연속된 값을 생성합니다.임의의 초기값을 선택할 수 있습니다.I
(씨앗이라고 불리는) 당신의 마음에 드는 것.물론 인라인으로 코드화할 수 있습니다.부호 없는 타입의 표준 보증 랩어라운드가 계수로서 기능합니다.(숫자 상수는 그 뛰어난 과학 프로그래머 도날드 크누스가 손으로 고른 것입니다.)
많은 좋은 답변들이 있지만, 다른 답을 덧붙여서 결정론적인 컴퓨터에서는 아무 것도 무작위적이지 않다는 점을 강조하겠습니다.이는 의사 RNG에 의해 생성되는 번호와 스택 상의 C/C++ 로컬 변수용으로 예약된 메모리 영역에 있는 것처럼 보이는 "랜덤" 번호 모두에 해당됩니다.
하지만... 결정적인 차이가 있어요
양호한 의사 난수 생성기에 의해 생성되는 숫자는 통계적으로 진짜 랜덤 드로잉과 유사한 속성을 가집니다.예를 들어 분포는 균일합니다.사이클 길이가 길다: 사이클이 반복되기 전에 수백만 개의 난수를 얻을 수 있다.시퀀스에는 자동 관련성이 없습니다.예를 들어, 2번째, 3번째, 27번째의 번호마다의 번호나 생성된 번호의 특정의 번호를 참조했을 경우, 이상한 패턴이 나타나는 일은 없습니다.
반대로 스택에 남겨진 "랜덤" 번호에는 이러한 속성이 없습니다.이들의 값과 겉으로 보이는 랜덤성은 전적으로 프로그램이 어떻게 구성되고 어떻게 컴파일되며 컴파일러에 의해 어떻게 최적화되는가에 달려있다.예를 들어, 다음은 자체 프로그램으로서의 아이디어의 변형입니다.
#include <stdio.h>
notrandom()
{
int r, g, b;
printf("R=%d, G=%d, B=%d", r&255, g&255, b&255);
}
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < 10; i++)
{
notrandom();
printf("\n");
}
return 0;
}
Linux 머신에서 GCC를 사용하여 이 코드를 컴파일하여 실행하면 다소 불쾌한 결정론적인 것으로 나타났습니다.
R=0, G=19, B=0
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
R=130, G=16, B=255
컴파일된 코드를 디스어셈블러로 보면 무슨 일이 일어나고 있는지 상세하게 재구성할 수 있습니다.notrandom()에 대한 첫 번째 호출에서는 이전에 이 프로그램에서 사용되지 않았던 스택 영역이 사용되었습니다.그 안에 무엇이 있는지 알 수 없습니다.단, notrandom()에 대한 호출 후에 printf()에 대한 호출(GCC 컴파일러는 실제로는 putchar()에 대한 호출로 최적화하지만, 이 호출은 스택을 덮어씁니다.따라서 다음 번 이후 notrandom()이 호출되면 스택에는 putchar() 실행에서 오래된 데이터가 포함됩니다.putchar()는 항상 같은 인수로 호출되므로 이 오래된 데이터도 항상 동일합니다.
따라서 이 동작에 랜덤한 것은 전혀 없습니다.또, 이 방법으로 취득한 수치에는, 올바르게 기술된 의사 난수 생성기의 바람직한 속성이 없습니다.실제로 대부분의 실제 시나리오에서 이들 값은 반복적이고 높은 상관관계를 보입니다.
사실, 다른 사람들과 마찬가지로, 나는 이 아이디어를 "고성능 RNG"로 전가하려는 사람을 해고하는 것을 심각하게 고려하고 있다.
아주 간단한 테스트를 했는데 전혀 무작위적인 테스트가 아니었어요.
#include <stdio.h>
int main() {
int a;
printf("%d\n", a);
return 0;
}
프로그램을 실행할 때마다 같은 번호가 출력되었습니다.32767
제 경우) -- 그보다 더 적은 랜덤은 없습니다.이것은 아마도 스택에 남아 있는 런타임 라이브러리의 시작 코드와 동일합니다.프로그램이 실행될 때마다 동일한 시작 코드를 사용하고 실행 간에 프로그램에서 다른 변화가 없기 때문에 결과는 완벽하게 일치합니다.
좋은 질문입니다!
정의되지 않았다는 것은 무작위라는 것을 의미하지 않습니다.글로벌 미초기화 변수에서 얻을 수 있는 값은 시스템 또는 실행 중인 다른 응용 프로그램에 의해 그대로 남아 있습니다.사용되지 않게 된 메모리의 사용 상황이나, 시스템과 애플리케이션이 생성하는 값의 종류에 따라서는, 다음과 같은 일이 있습니다.
- 항상 같다.
- 작은 가치관 중 하나가 되십시오.
- 하나 이상의 작은 범위에서 값을 가져옵니다.
- 16/32/64비트 시스템의 포인터에서 2/4/8로 나눌 수 있는 많은 값 보기
- ...
얻을 수 있는 값은 시스템 및/또는 애플리케이션이 남기는 랜덤 이외의 값에 따라 완전히 달라집니다.따라서 실제로 약간의 노이즈가 발생하지만(시스템이 더 이상 사용되지 않는 메모리를 지우지 않는 한), 추출하는 값 풀은 결코 랜덤이 아닙니다.
로컬 변수는 프로그램 스택에서 직접 생성되므로 상황이 훨씬 악화됩니다.프로그램이 다른 코드를 실행하는 동안 실제로 이러한 스택 위치를 기록할 가능성이 매우 높습니다.이 상황에서 행운의 가능성은 매우 낮으며, '랜덤' 코드 변경이 이 행운을 시도합니다.
무작위성에 대해 읽어보십시오.보시다시피 무작위성은 매우 구체적이고 얻기 어려운 특성입니다.추적하기 어려운 것(예: 제안 사항)만 취하면 랜덤 값을 얻을 수 있다고 생각하는 것은 흔한 실수입니다.
초기화되지 않은 메모리가 "unsigned char*" 타입을 사용하여 안전하게 읽을 수 있는 상황이 있습니다.[예를 들어 버퍼가 반환되는 경우]malloc
컴파일러가 창 밖으로 원인을 던질 염려 없이 코드를 읽을 수 있으며, 초기화되지 않은 데이터를 읽지 않도록 하는 것보다 메모리에 포함되어 있는 모든 것에 대해 코드를 준비하는 것이 더 효율적일 수 있습니다(일반적인 예로는 를 사용하는 경우가 있습니다.memcpy
의미 있는 데이터를 포함하는 모든 요소를 개별적으로 복사하지 않고 부분적으로 초기화된 버퍼에 저장합니다).
다만, 이러한 경우에서도, 바이트의 편성이 특히 귀찮은 경우, 그 바이트의 패턴을 읽어내는 것은 항상 그 패턴을 낳는다고 가정할 필요가 있습니다(또한, 특정 패턴이 귀찮은 경우는, 개발에서는 귀찮지만, 그러한 패턴은, 코드가 실전 가동할 때까지는 표시되지 않습니다).
초기화되지 않은 메모리를 읽어내는 것은 임베디드 시스템에서 랜덤 생성 전략의 일부로서 도움이 됩니다.이 전략의 일부에서는 시스템 전원을 마지막으로 켠 이후 메모리가 실질적으로 랜덤하지 않은 콘텐츠로 기록된 적이 없으며, 메모리에 사용된 제조 프로세스로 인해 메모리 전원이 켜지는 상태가 반랜덤으로 변화하는지 확인할 수 있습니다.패션.코드는 모든 장치가 항상 동일한 데이터를 생성하는 경우에도 작동해야 하지만, 예를 들어 노드 그룹이 가능한 한 빨리 임의의 고유 ID를 선택해야 하는 경우, 노드의 절반에 동일한 초기 ID를 제공하는 "매우 랜덤하지 않은" 생성기를 갖는 것이 랜덤성의 초기 소스를 전혀 가지지 않는 것보다 나을 수 있습니다.
정의되지 않은 동작은 프로그래머가 어떤 일이 일어나도 불평할 권리가 없기 때문에 컴파일러 작성자들이 문제를 무시할 수 있다는 것을 의미합니다.
이론적으로 UB랜드에 들어가면 어떤 일도 일어날 수 있지만(데몬이 코앞으로 날아가는 것을 포함), 보통 컴파일러 작성자는 신경쓰지 않고 로컬 변수의 경우 그 시점에서 스택메모리의 값이 무엇이든지 됩니다.
이것은 또한 종종 내용이 "이상한" 것이지만 고정적이거나 약간 랜덤하거나 가변적이지만 분명한 패턴(예: 각 반복마다 값이 증가함)을 갖는다는 것을 의미합니다.
확실히 당신은 그것이 괜찮은 무작위 발생기를 기대할 수 없습니다.
정의되지 않은 동작이 정의되지 않았습니다.이는 정의되지 않은 값을 얻는 것이 아니라 프로그램이 모든 작업을 수행하면서도 언어 사양을 충족할 수 있음을 의미합니다.
최적의 컴파일러는
void updateEffect(){
for(int i=0;i<1000;i++){
int r;
int g;
int b;
star[i].setColor(r%255,g%255,b%255);
bool isVisible;
star[i].setVisible(isVisible);
}
}
한밤중으로 컴파일 할 수 있습니다.이것은 확실히 다른 어떤 대안보다 빠르다.아무것도 하지 않을 것이라는 단점이 있지만, 그것이 정의되지 않은 행동의 단점이다.
보안상의 이유로 프로그램에 할당된 새 메모리를 청소해야 합니다.그렇지 않으면 정보가 사용되거나 어떤 애플리케이션에서 다른 애플리케이션으로 비밀번호가 유출될 수 있습니다.메모리를 재사용하는 경우에만 0과 다른 값을 얻을 수 있습니다.또한 스택에서는 이전 메모리의 사용이 고정되어 있기 때문에 이전 값이 고정되어 있을 가능성이 높습니다.
특정 코드 예에서는 예상대로 되지 않을 수 있습니다.엄밀히 말하면 루프를 반복할 때마다 r, g 및 b 값의 로컬 변수가 다시 작성되지만 실제로는 스택상의 메모리공간과 동일합니다.따라서 반복할 때마다 재랜덤화되지 않고 r, g 및 b가 개별적으로 얼마나 랜덤한지와 관계없이 1000개의 색상 각각에 동일한 3개의 값을 할당할 수 있습니다.
과연, 만약 그것이 효과가 있었다면, 나는 무엇이 그것을 다시 랜덤화하는지 매우 궁금했을 것이다.내가 생각할 수 있는 유일한 것은 인터리브 인터럽트일 것이다. 그 스택 위에 가득 채워진 인터럽트일 가능성이 매우 희박하다.레지스터가 루프에서 더 아래쪽으로 재사용되는 실제 메모리 위치가 아닌 레지스터 변수로 유지되는 내부 최적화는 특히 설정된 가시성 함수가 레지스터를 필요로 하는 경우에도 효과가 있을 수 있습니다.그래도, 무작위와는 거리가 멀죠.
여기 있는 대부분의 사람들이 정의되지 않은 행동을 언급했듯.정의되지 않음은 유효한 정수값을 얻을 수 있음을 의미하기도 합니다(다행히).이 경우 랜드 함수 호출이 이루어지지 않기 때문에 이 값이 더 빨라집니다.하지만 실제로는 사용하지 마세요.행운이 항상 당신에게 있는 것은 아니기 때문에, 이것은 끔찍한 결과가 될 것이라고 확신합니다.
정말 안 좋아!나쁜 습관, 나쁜 결과.고려사항:
A_Function_that_use_a_lot_the_Stack();
updateEffect();
함수가A_Function_that_use_a_lot_the_Stack()
항상 같은 초기화를 실시해, 같은 데이터를 스택에 남깁니다.그 데이터는 우리가 부르는 것이다.updateEffect()
: 항상 같은 값!
아직 언급되지 않았지만, 정의되지 않은 동작을 호출하는 코드 경로는 컴파일러가 원하는 대로 할 수 있습니다.
void updateEffect(){}
UB를 통해 올바른 루프보다 더 빠르고 완벽하게 호환됩니다.
초기화되지 않은 데이터를 랜덤성에 사용하는 것이 반드시 나쁜 것은 아닙니다.실제로 OpenSSL은 PRNG를 시드하기 위해 이 작업을 수행합니다.
그러나 Valgrind가 초기화되지 않은 데이터를 사용하는 것에 대해 불만을 제기하고 "수정"하여 PRNG에 버그를 발생시켰기 때문에 이 사용법이 제대로 문서화되지 않은 것으로 보입니다.
할 수 있지만, 자신이 무엇을 하고 있는지 알아야 하고 코드를 읽는 사람이 이 점을 이해하도록 해야 합니다.
당신은 '랜덤'이 무엇을 의미하는지 정의할 필요가 있다.합리적인 정의에는 얻을 수 있는 값이 거의 상관 관계가 없어야 합니다.그건 네가 측정할 수 있는 거야.또한 제어되고 재현 가능한 방법으로 달성하는 것도 간단하지 않습니다.그래서 정의되지 않은 행동은 확실히 당신이 원하는 것이 아니다.
다른 사람들이 말했듯이, 그것은 빠르겠지만 무작위는 아니다.
대부분의 컴파일러가 로컬 변수에 대해 수행하는 것은 스택상의 공간을 확보하는 것입니다만, 아무것도 설정하지 않아도 됩니다(표준에서는 불필요하다고 되어 있습니다만, 생성하는 코드의 속도를 늦출 필요는 없습니다).
이 경우 얻을 수 있는 값은 스택 상의 이전에 무엇이냐에 따라 달라집니다.모든 로컬 문자 변수가 'Q'로 설정되어 있는 함수를 호출하고 그 후에 함수임을 호출하면 랜덤 값이 다음과 같이 동작하는 것을 알 수 있습니다.memset()
모두 'Q'에 맞춰요
이 기능을 사용하려고 하는 예제 함수에서 중요한 것은 이러한 값은 읽을 때마다 변경되지 않고 매번 동일합니다.따라서 100개의 별을 모두 동일한 색상과 가시성으로 설정할 수 있습니다.
또, 컴파일러가 이러한 값을 초기화하지 않는 것은 없습니다.따라서, 장래의 컴파일러가 초기화할 가능성이 있습니다.
일반적으로: 잘못된 생각, 실행하지 마십시오. (많은 "깨끗한" 코드 레벨 최적화처럼...)
이미 언급한 바와 같이 이는 정의되지 않은 동작(UB)이지만 "작동"할 수 있습니다.
다른 사람이 이미 언급한 문제를 제외하고, 다른 문제(장점)가 하나 있습니다.C 및 C++ 이외의 언어에서는 동작하지 않습니다.이 질문은 C++에 관한 것으로 알고 있습니다만, C++와 Java 코드에 맞는 코드를 쓸 수 있고 문제가 되지 않는다면 왜 안 될까요?언젠가는 다른 언어로 옮겨야 할 날이 올지도 모릅니다.그리고 이와 같은 "마법의 속임수" UB에 의한 버그를 찾는 것은 확실히 악몽이 될 것입니다(특히 경험이 부족한 C/C++ 개발자에게는 더욱 그렇습니다.
여기 또 다른 유사한 UB에 대한 질문이 있습니다.이 UB에 대해 모르고 이런 버그를 찾으려 한다고 상상해 보세요.C/C++에 기재되어 있는 이상한 것에 대해 자세히 읽고 싶다면 링크의 질문에 대한 답변을 읽고 이 GREAT 슬라이드 쇼를 참조하십시오.이 슬라이드 쇼에서는, 「매직」으로 가득 찬 슬라이드 쇼 뿐만이 아닙니다.경험이 많은 C/C++ 프로그래머들도 이 일을 통해 많은 것을 배울 수 있을 것이라고 확신합니다.
우리의 논리를 언어의 정의되지 않은 행동에 의존하는 것은 좋은 생각이 아니다.이 투고에서 언급/논의한 내용 외에, 나는 현대의 C++ 접근법/스타일로는 그러한 프로그램이 컴파일되지 않을 수 있다는 것을 언급하고 싶다.
이것은 이전 투고에서 언급되었으며, 자동 기능의 장점과 이에 대한 유용한 링크가 포함되어 있습니다.
https://stackoverflow.com/a/26170069/2724703
따라서 위의 코드를 변경하고 실제 유형을 auto로 바꾸면 프로그램이 컴파일조차 되지 않습니다.
void updateEffect(){
for(int i=0;i<1000;i++){
auto r;
auto g;
auto b;
star[i].setColor(r%255,g%255,b%255);
auto isVisible;
star[i].setVisible(isVisible);
}
}
당신의 사고방식이 마음에 들어요.정말 틀에서 벗어났어.하지만 그 균형은 정말 가치가 없다.메모리 런타임에 대한 정의되지 않은 동작을 포함하여 메모리 런타임의 트레이드오프는 중요합니다.
그런 '랜덤'을 비즈니스 로직으로 사용하고 있다는 것을 알면 매우 불안할 것입니다.난 안 할 거야.
사용하다7757
초기화되지 않은 변수를 사용하고 싶은 모든 장소.소수 목록에서 무작위로 골랐어요
그것은 정의된 행동이다.
반드시 0이 되는 것은 아닙니다.
프라임
초기화되지 않은 변수만큼 통계적으로 무작위일 가능성이 높다
컴파일 시에 값이 알려져 있기 때문에 초기화되지 않은 변수보다 빠를 수 있습니다.
고려해야 할 가능성이 하나 더 있습니다.
최신 컴파일러(ahem g++)는 매우 인텔리전트하기 때문에 어떤 명령어가 상태에 영향을 미치는지, 어떤 명령어가 상태에 영향을 미치지 않는지 확인하기 위해 코드를 조사합니다.또한 명령어가 상태에 영향을 주지 않는 것이 보증되면 g++는 명령어를 삭제합니다.
그래서 무슨 일이 일어날지 알려줄게.g++는 읽기, 산술 실행, 저장, 본질적으로 가비지 값인 가비지 값이 더 많이 생성되는 것을 분명히 알 수 있습니다.새로운 쓰레기가 오래된 쓰레기보다 더 유용하다는 보장은 없기 때문에 단순히 루프를 없앨 수 있습니다.빵!
이 방법은 유용하지만, 제가 할 일은 이렇습니다.UB(Undefined Behavior)를 rand() 속도와 결합합니다.
물론, 삭감합니다.rand()
s는 실행되지만 컴파일러가 원하지 않는 작업을 수행하지 않도록 혼합합니다.
그리고 난 널 해고하지 않을 거야.
언급URL : https://stackoverflow.com/questions/31739792/is-uninitialized-local-variable-the-fastest-random-number-generator
'programing' 카테고리의 다른 글
프로그램이 32비트 또는 64비트라는 것은 무엇을 의미합니까? (0) | 2022.07.31 |
---|---|
Waitpid는 타임아웃과 동등합니까? (0) | 2022.07.31 |
Vue/Vuex에 mapStateToProps와 같은 리액션/리듀스가 있습니까? (0) | 2022.07.31 |
Github 페이지에 게시된 Vue 웹 사이트를 새로고침할 때 404 (0) | 2022.07.31 |
Time Unit 열거를 사용하여 나노초를 초로 변환하려면 어떻게 해야 합니까? (0) | 2022.07.31 |