Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Operacje na wskaźniku - kiedy standard określa niezdefiniowane zachowanie?

Ostatnio zmodyfikowano 2015-01-05 21:52
Autor Wiadomość
antonio12
Temat założony przez niniejszego użytkownika
[C++] Operacje na wskaźniku - kiedy standard określa niezdefiniowane zachowanie?
» 2015-01-03 17:59:39
Mam taki program:
C/C++
#include <stdio.h>

int main()
{
    char c1, c2;
    char tekst[] = "kolorowo";
    for( c1 =*( tekst - 1 + strlen( tekst ) ), c2 =* tekst; c1-->c2; )
    {
        switch( c1 )
        {
        case 'o': printf( "^ " ); c2++;
        case 'l': printf( "* " ); break;
        case 'k': printf( "& " ); c2++; break;
        case 'm': printf( "% " );
        case 'r': printf( "# " ); break;
            default: printf( "%c %c ", c1, c2 ); c2++;
        }
    }
   
    return 0;
}

Po skompilowaniu go wyskakuje: n k # *

Ale skąd te n jak nigdzie nie ma tego w switchu ?
P-123964
Monika90
» 2015-01-03 18:05:13
Moim zdaniem program ma niezdefiniowane zachowanie! Ze względu na to podwyrażenie:
tekst - 1
, jest to wskaźnik do elementu przed początkiem tablicy, takie wskaźniki nie są dozwolone.
P-123965
antonio12
Temat założony przez niniejszego użytkownika
» 2015-01-03 19:17:27
dziwne że jest błąd bo takie zadania dostaliśmy od prowadzącego
P-123978
DejaVu
» 2015-01-03 19:27:30
Rzadko kiedy na uczelni jakikolwiek profesor/doktorant nauczający programowania ma pojęcie, że istnieje coś takiego jak 'niezdefiniowane zachowanie' aplikacji. Dla nich w większości przypadków argumentem jest wynik działania kodu na jego kompilatorze - chyba, że ktoś mu wytknie błąd merytoryczny i pokaże, że na innym kompilatorze aplikacja zachowuje się inaczej oraz powoła się na standard. Problem w tym, że na uczelni się tego zwyczajowo nie robi, bo po co generować sobie problemy i tym samym dyskredytować wiedzę prowadzących zajęcia. Dodam jeszcze, że nawet doświadczone osoby w programowaniu potrafią rzucić kod z niezdefiniowanym zachowaniem na teście rekrutacyjnym i później upierać się, że wynik wychodzi XYZ, ponieważ 'on ten kod kompilował i sprawdzał' (zdarzyło mi się uczestniczyć w takim procesie rekrutacyjnym).

Niemniej jednak pomimo, że kod ma niezdefiniowane zachowanie wg standardu to prawdopodobnie zachowa on się tak samo na wszystkich kompilatorach, ponieważ długość tekstu jest większa od zera oraz adres pamięci ostatecznie nie uzyska nieoczekiwanej wartości w wyniku takich operacji (czytaj: nie zajdzie underflow, więc adresowanie ostatecznie będzie poprawne).

/edit:
Jeszcze trochę 'podparcia':
http://stackoverflow.com​/questions/10011372​/c-underflow-and-overflow
Typically yes. But since this is C++, and C++ is regulated by the C++ standard, you must know that overflows are undefined behavior.

http://stackoverflow.com​/questions/3679047​/integer-overflow-in-c-standards-and-compilers

For your C99 answer, I think 6.5 Expressions, paragraph 5 is what you're looking for:

If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined.

That means if you get an overflow, you're out of luck - no behaviour of any kind guaranteed. Unsigned types are a special case, and never overflow (6.2.5 Types, paragraph 9):

A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

C++ has the same statements, worded a bit differently:

5 Expressions, paragraph 4:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [Note: most existing implementations of C++ ignore integer overflows. Treatment of division by zero, forming a remainder using a zero divisor, and all floating point exceptions vary among machines, and is usually adjustable by a library function. —endnote]

3.9.1 Fundamental types, paragraph 4:

Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2^n where n is the number of bits in the value representation of that particular size of integer.
P-123979
1aam2am1
» 2015-01-03 19:35:59
Co to robi?
c1-->c2;
P-123980
DejaVu
» 2015-01-03 19:39:45
C/C++
c2 =* tekst; c1-- > c2;
P-123981
SocrateZ
» 2015-01-03 19:42:47
Ze względu na to podwyrażenie: tekst - 1, jest to wskaźnik do elementu przed początkiem tablicy, takie wskaźniki nie są dozwolone.
Zgodziłbym się z tym gdyby to było całe wyrażenie. Tutaj jest całość:
tekst - 1 + strlen( tekst )


Po prostu pobiera ostatni znak. W pętli for wyświetla k i n.
Pytanie było DLACZEGO n?
Już wyjaśniam. Ponieważ w pętli for c1-- > c2 jest w miejscu PORÓWNANIA. Co oznacza że c1 po przypisaniu wartości jest odejmowane. A w znakach ASCII przed znakiem o jest znak n.


for( x ; y ; z ) tutaj brakuje elementu z który jest wykonywany po pojedynczym przebiegu pętli. Element Y wykonywany jest na początku pętli, zaraz po elemencie X.
Dodatkowo należy dodać bibliotekę string.h dla funkcji strlen.

Zagadka rozwiązana.

Moim zdaniem program ma niezdefiniowane zachowanie!
I właśnie w związku z powyższym zachowanie to nie jest niezdefiniowane. Jest ono do przewidzenia, a profesor dał całkiem ciekawą zagadkę :)
P-123982
DejaVu
» 2015-01-03 19:50:12
Moim zdaniem program ma niezdefiniowane zachowanie!
I właśnie w związku z powyższym zachowanie to nie jest niezdefiniowane!
C/C++
tekst - 1 + strlen( tekst )
Jeżeli tekst miałby przypisany wskaźnik 0 to wówczas byłoby to niezdefiniowane zachowanie, ponieważ:
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined
Jeżeli tekst byłby pusty to zapis również miałby niezdefiniowane zachowanie, ponieważ wychodziłby poza zakres tablicy.
P-123983
« 1 » 2 3 4 5 6 7 8
  Strona 1 z 8 Następna strona