Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Για ποιο λογο να αγορασει καποιος βιβλιο απο amazon την ιδια στιγμη που το bookdepository εχει δωρεαν μεταφορικα και σχετικα πιο καλες τιμες?

Εννοείται πως αν το βρεις πιο φθηνά αλλού το παίρνεις από εκεί. Ο μόνος λόγος που έβαλα το amazon ήταν γιατί μου φάνηκε πιο φθηνό (με ένα γρήγορο ψάξιμο, το amazon το είχε καμμιά 50αριά λίρες ενώ το bd καμμιά 90αριά λίρες).

 

εγω ισως να μην ήμουν τοσο ψειρας

Σε πολλά από αυτά όντως είμαι ψείρας.

 

Το πρόβλημα όμως είναι ότι έστω και λίγα από αυτά πρέπει να τα ξέρεις αλλιώς θα οδηγηθείς σε bugs. Αυτό το γεγονός ότι πρέπει να γνωρίζεις λεπτομέρειες χαμηλού επιπέδου είναι και ένας από τους λόγους (μεταξύ άλλων) που πολλοί εδώ στο φόρουμ προτείνουν στον κόσμο να μην ασχολείται με C αλλά να κοιτάξει κάτι άλλο.

  • Απαντ. 38
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοφιλείς Ημέρες

Δημοσ.

Εννοείται πως αν το βρεις πιο φθηνά αλλού το παίρνεις από εκεί. Ο μόνος λόγος που έβαλα το amazon ήταν γιατί μου φάνηκε πιο φθηνό (με ένα γρήγορο ψάξιμο, το amazon το είχε καμμιά 50αριά λίρες ενώ το bd καμμιά 90αριά λίρες).

 

Σε πολλά από αυτά όντως είμαι ψείρας.

 

Το πρόβλημα όμως είναι ότι έστω και λίγα από αυτά πρέπει να τα ξέρεις αλλιώς θα οδηγηθείς σε bugs. Αυτό το γεγονός ότι πρέπει να γνωρίζεις λεπτομέρειες χαμηλού επιπέδου είναι και ένας από τους λόγους (μεταξύ άλλων) που πολλοί εδώ στο φόρουμ προτείνουν στον κόσμο να μην ασχολείται με C αλλά να κοιτάξει κάτι άλλο.

 

Δυσκολα θα βρεις προγραμμα χωρις bug :D το βιβλιο δεν το έχω διαβασει αλλα αμα του ξέφυγε το int *p1 , p2; και εγραψε οντως οτι και η p2 σε αυτη τη περιπτωση δηλώνεται σαν μεταβλητη δεικτη τοτε ειναι χοντρο. Αλλα εντάξει να ξεφυγει τωρα ενα int main() αντι για int main(void) αυτο τι bug μπορει να δωσει? σε διαγωνισμα να το εβλεπα και να με βάζανε να το διορθωσω δεν θα έκοβα ουτε 1 στα 100.

 

Κατα τα αλλα συμφωνω για τα περισσοτερα πχ και το char ch;  ch = getchar(); ειναι λάθος κανονικα.Κάποιο λογο θα έχουν που έχουν βαλει την συνάρτηση αυτη να έχει επιστρεφομενο τύπο int και οχι char. Ακομα και αν δεν ξέρει κάποιος για το EOF αν ειναι λιγάκι πονηρος μπορει να το σκεφτει.

Δημοσ.

Για άλλη μια φορά ξεφεύγουμε από το θέμα αλλά ίσως αποτελέσει κίνητρο στον OP να ασχοληθεί με κάποια άλλη γλώσσα :P

 

Ημίθεε, αφού επιμένουν στις σχολές με τα ελληνικά, αν δεν το έχεις κάνει ήδη, κάτσε γράψε ένα βιβλίο. :P

Αν έγραφα εγώ ένα βιβλίο θα ήταν πάραααα πολύ χάλια :P Εδώ ένα μήνυμα γράφω εδώ και το αλλάζω 30 φορές για να διαβάζεται (και πάλι δεν διαβάζεται πολλές φορές).

 

Δεν θέλω τα μηνύματά μου να εκληφθούν ότι δεν θεωρώ καλό το βιβλίο. Μια χαρά είναι απλά επισήμανα κάποια πράγματα που δεν μου αρέσουν, το οποίο πιστεύω είναι πιο επικοδομητικό από το να γραφτεί ένα βιβλίο ξανά από την αρχή (και ειδικά από κάποιον τύπο σαν εμένα :P)

 

Αλλα εντάξει να ξεφυγει τωρα ενα int main() αντι για int main(void) αυτο τι bug μπορει να δωσει?

Αν ψάξεις λίγο παλαιότερα μηνύματα που μιλούσε ο defacer για undefined behavior θα δεις ότι δυστυχώς η κατάσταση δεν είναι τόσο απλή στην C. Ας πάρουμε ένα από τα παραδείγματα που ανέφερα πριν.

 

 

 

FILE *fp;
char ch;

fp = fopen("text.txt", "r");
if (fp == NULL) exit(2);

while (ch!=EOF)
{
blah
}
Το ότι χρησιμοποιεί το ch χωρίς να έχει θέσει πρώτα μια τιμή, σιγά το πράγμα πια. Σε τι bug μπορεί να οδηγήσει ? Ας σου το κάνω πιο απλό ακόμη.

 

#include <stdio.h>

int main(void)
{
	int i;

	printf("i equals i ? = %d\n", i == i);
	return 0;
}
Compilation:

% gcc -Wall -O0 -o gcc0 tmp.c 
% gcc -Wall -O2 -o gcc2 tmp.c  
% clang -Wall -O0 -o cl0 tmp.c 
tmp.c:7:34: warning: self-comparison always evaluates to true
      [-Wtautological-compare]
        printf("i equals i ? = %d\n", i == i);
                                        ^
tmp.c:7:32: warning: variable 'i' is uninitialized when used here
      [-Wuninitialized]
        printf("i equals i ? = %d\n", i == i);
                                      ^
tmp.c:5:7: note: initialize the variable 'i' to silence this warning
        int i;
             ^
              = 0
2 warnings generated.

% clang -Wall -O2 -o cl2 tmp.c  
ίδια warnings
Έξοδος:

% ./gcc0 
i equals i ? = 1
% ./gcc2 
i equals i ? = 1
% ./cl0 
i equals i ? = 1
% ./cl2 
i equals i ? = 0
Oops. Τρέχα βρες τώρα ποιο είναι το bug και δεν παίζει σωστά ο κώδικάς σου. Σε άλλες γλώσσες δεν χρειάζεται να φας τον χρόνο σου ώστε να μάθεις ότι αν χρησιμοποιήσεις μια μεταβλητή (πιο σωστά μια non-static και non-global μεταβλητή) χωρίς να την αρχικοποιήσεις, τότε μπορεί ο compiler να κάνει ό,τι θέλει.

 

Σε C πρέπει να το γνωρίζεις γιατί όπως είδες, ακόμη και ενώ σου εμφανίζει warning ότι self-comparison είναι always true, να που δεν είναι.

 

 

Δημοσ.

Κι αυτό είναι καλό: Link.png Site: C :από τη Θεωρία στην Εφαρμογή  . Είναι καλογραμμένο, και δε χάνεται σε λεπτομέρειες αλλά σου δίνει ξεκάθαρα τη βασική ιδέα κι έχει πολλά παραδείγματα. Το μόνο σοβαρό "πρόβλημα" που θυμάμαι είναι χρήση gets σε κάποιο παράδειγμα, αλλά τουλάχιστον στο σχετικό κεφάλαιο έλεγε ότι δεν πρέπει να χρησιμοποιείται. Επίσης, έχει αρκετά ελαφριά κάλυψη αναδρομής.

  • Like 1
Δημοσ. (επεξεργασμένο)

Κι αυτό είναι καλό: Είναι καλογραμμένο, και δε χάνεται σε λεπτομέρειες αλλά σου δίνει ξεκάθαρα τη βασική ιδέα κι έχει πολλά παραδείγματα. Το μόνο σοβαρό "πρόβλημα" που θυμάμαι είναι χρήση gets σε κάποιο παράδειγμα, αλλά τουλάχιστον στο σχετικό κεφάλαιο έλεγε ότι δεν πρέπει να χρησιμοποιείται. Επίσης, έχει αρκετά ελαφριά κάλυψη αναδρομής.

Δεν το έχω διαβάσει οπότε δεν θέλω να κρίνω βιαστικά αλλά από τις ενδεικτικές ασκήσεις που βλέπω, δεν ενθουσιάζομαι και πολύ. Μου φαίνεται απίθανο να είναι μόνο πρόβλημα η χρήση gets.

 

Άσκηση Ε.10

#include <stdio.h>
#include <string.h>

int main()
{
	char str[10] = "test";
	printf("%d %s\n", *strcpy(str, "n")**strcpy(str+2, "xt"), str);
	return 0;
}
Τι διδάσκει η παραπάνω άσκηση εκτός από άχρηστο μακαρονοκώδικα ? Επίσης, σε μια λίγο διαφορετική άσκηση, δεν θα μπορούσες να απαντήσεις, γιατί το "order of evaluation" εξαρτάται από τον compiler. Ένας compiler μπορεί να τρέξει πρώτα το δεύτερο strcpy και μετά το πρώτο (στην προκειμένη περίπτωση βέβαια το αποτέλεσμα θα είναι το ίδιο).

 

Άσκηση Ε.12

#include <stdio.h>
#include <string.h>

int main()
{
	char  *ptr, str[] = "Text";
	int i;

	ptr = str;
	for (i = 0; i < strlen(str); i++)
	{
		printf("%c", ptr[i]);
		ptr++;
	}
	return 0;
}
Η συγκεκριμένη άσκση οδηγεί σε undefined behavior γιατί βγαίνει εκτός ορίων. Αν προσέξεις το βρόχο, ταυτόχρονα και αυξάνει τον ptr και προσπελαύνει το iοστό στοιχείο του. Έτσι στην αρχή ο ptr θα δείχνει στο str και θα προσπελάσει το 0 στοιχείο δηλαδή το T. Έπειτα, θα προσπελάσει το στοιχείο 1 (δηλαδή το δεύτερο) αλλά ο ptr ήδη δείχνει στο 2ο οπότε το 3ο στοιχείο. Μετά θα προσπελάσει το 5ο και τέλος το 7ο στοιχείο σε ένα πίνακα 5 στοιχείων.

 

Ή οι ασκήσεις είναι επίτηδες γραμμένες έτσι ώστε να σε μάθουν να βρίσκεις την κακή πρακτική και να μην την κάνεις (αμφίβολο) ή οι ασκήσεις είναι κακογραμμένες :)

 

Edit: Δεν είχα συνεχίσει πέρα από αυτές τις ασκήσεις αλλά τώρα που είδα όλο το pdf, τελικά στο τέλος έχει και λύσεις για αυτές και από την εξήγηση συμπεραίνω ότι όντως είναι επίτηδες γραμμένες έτσι.

Επεξ/σία από imitheos
Δημοσ.

Μπορεί κανείς να τρέξει το κώδικα εδώ: http://www.tutorialspoint.com/compile_c_online.php

Το δεύτερο προγραμματάκι βγάζει το Tx ως αποτέλεσμα.

Σίγουρα όμως βασίζεται στη λογική ότι ο χώρος που δίνεται για τον πίνακα έχει και πρόσθετα αδιάθετα bytes. Να γιατί και το On line παίζει!

Δημοσ.

Μπορεί κανείς να τρέξει το κώδικα εδώ: http://www.tutorialspoint.com/compile_c_online.php

Το δεύτερο προγραμματάκι βγάζει το Tx ως αποτέλεσμα.

Σίγουρα όμως βασίζεται στη λογική ότι ο χώρος που δίνεται για τον πίνακα έχει και πρόσθετα αδιάθετα bytes. Να γιατί και το On line παίζει!

 

Το δεύτερο πρόγραμμα δε βγάζει "Tx" ως αποτέλεσμα. Σου φαίνεται ότι βγάζει αυτό, αλλά είναι προφανές ότι αν δεν είχε UB θα τύπωνε ακριβώς τέσσερις χαρακτήρες, και αυτό κάνει στην πράξη. Απλά οι δύο τελευταίοι τυχαίνει να μην είναι printable.

 

Ο λόγος που παίζει είναι ότι UB. Και ο λόγος που μπορεί να μην παίξει είναι πάλι UB. Δεν έχει καμία σχέση αν ο πίνακας έχει "αδιάθετα" bytes, και επίσης ο πίνακας που ορίζεται με τέτοιο τρόπο δεν έχει παραπάνω bytes.

Δημοσ.

Δεν μπορω να καταλαβω ποια ειναι ακριβως η σημασια της Ε.12 μπορει να γραφει πολυ πιο απλά :

 
#include <stdio.h>
#include <string.h>

int main()
{
    char  *ptr, str[] = "Text";
    int i;

    ptr = str;
    for (i = 0; i < strlen(str); i++)
        printf("%c", *ptr++);

    return 0;
}
 

ή πιο απλά

 
#include <stdio.h>

int main()
{
    char  *ptr, str[] = "Text";

    for (ptr=str; *ptr!='\0'; ptr++)
        printf("%c", *ptr);

    return 0;
}
  • Like 1
Δημοσ.
#include <stdio.h>

int main()
{
    char str[] = "Text";
        printf("%s", &str);
    return 0;
}

και αυτό θα μπορούσε να κάνει για να πετάξει το for...

Δημοσ.
#include <stdio.h>

int main()
{
    char str[] = "Text";
        printf("%s", &str);
    return 0;
}

και αυτό θα μπορούσε να κάνει για να πετάξει το for...

 

#include <stdio.h>

int main(){
    printf("Text");
    return 0;
}

και αυτό μπορεί να πετάξει το str... (δεν είναι αυτή η ουσία να πετάμε πραγματα ...)

  • Like 1
Δημοσ.

Πάντως για να μιλάμε για το 2016...έχει πεθάνει το 8bit char, οπότε το βιβλίο μάλλον ΔΕΝ κάνει!

Το δεύτερο το πρόσθεσα για να φανεί και ο ορθός τρόπος...(χωρίς χρήση pointer, αλλά με offset)

με αλλαγή  wprintf(L"%ls", &str); παίρνουνε το string από ένα σημείο και μετά!

#include <stdio.h>
#include <stddef.h>

int main()
{
    wchar_t str[] = L"Text\n";
        wprintf(L"%ls", &str);
    return 0;
}
#include <stdio.h>
#include <stddef.h>

int main()
{
    int i=0;
    wchar_t str[] = L"Text\n";
        wprintf(L"%ls", &str);
    for( ;str[i]>0;i++)
        wprintf(L"%lc", str[i]);
    return 0;
}

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...