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

Ερωτήσεις για C


capoelo

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

Σωστός!

 

:)

 

Είναι αυτό που ανέφερα 2-3 φορές ότι πρόκειται περί ισοδυναμίας (και όχι ισότητας).

 

Επίσης, είναι κομματάκι tricky το που κάνεις cast σε ** τον 2D. Για παράδειγμα αν μέσα στη συνάρτηση κάνεις cast τον walk σε ** ...

int **walk = (int **) arrInt2d;

πιθανότατα θα έχεις πρόβλημα κατόπιν στην διαχείρισή του, λόγω της διαφοράς lvalue μεταξύ 2Δ και ** (δεν έχω τώρα χρόνο να το δοκιμάσω, αλλά είμαι 99,9% σίγουρος πως θα βαρέσει seg-fault).

 

Ο κώδικας που έδωσα κάνει επίτηδες μέσα στη συνάρτηση cast μονάχα στο deeper level του 2Δ, δηλαδή στο 1ο στοιχείο του 2D ...

int *walk = (int *) arrInt2d;

;)

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 1,6k
  • Δημ.
  • Τελ. απάντηση

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

@migf1


Δεν είναι καλή ιδέα να περιπλέκεις έτσι την κλήση των macros, γιατί έχουν πολλά pitfalls. Είναι πολύ χρήσιμα όταν τα κρατάς και τα χρησιμοποιείς όσο πιο απλά μπορείς (εκτός αν δεν γίνεται αλλιώς).

 

Συμφωνοι. Αλλα κανονικα ετσι παει και τον τριαδικο τον θεωρει εναν τελεστη για να μπαινει μονο ενα ζευγος. Αυτο ρωτησα εγω βασικα δεν σου ειπα οτι θα το χρησιμοποιω στα προγραμματα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@migf1

 

Δεν είναι καλή ιδέα να περιπλέκεις έτσι την κλήση των macros, γιατί έχουν πολλά pitfalls. Είναι πολύ χρήσιμα όταν τα κρατάς και τα χρησιμοποιείς όσο πιο απλά μπορείς (εκτός αν δεν γίνεται αλλιώς).

 

Συμφωνοι. Αλλα κανονικα ετσι παει και τον τριαδικο τον θεωρει εναν τελεστη για να μπαινει μονο ενα ζευγος. Αυτο ρωτησα εγω βασικα δεν σου ειπα οτι θα το χρησιμοποιω στα προγραμματα.

 

Καλημέρα,

 

δεν έχω καταλάβει ποια ακριβώς είναι η ερώτηση. Αν ρωτάς πως πρέπει να πάνε οι παρενθέσεις στο συγκεκριμένο παράδειγμα, δεν έχω κίνητρο να το ψάξω γιατί προσωπικά ποτέ δεν καλώ macros  περνώντας τον εαυτό τους ως όρισμα (και δεν το συστήνω κιόλας).

 

Αν είναι άλλη η ερώτηση, διατύπωσέ την λίγο πιο ξεκάθαρα για να βοηθήσουμε αν μπορούμε.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Καλημέρα,

 

δεν έχω καταλάβει ποια ακριβώς είναι η ερώτηση. Αν ρωτάς πως πρέπει να πάνε οι παρενθέσεις στο συγκεκριμένο παράδειγμα, δεν έχω κίνητρο να το ψάξω γιατί προσωπικά ποτέ δεν καλώ macros  περνώντας τον εαυτό τους ως όρισμα (και δεν το συστήνω κιόλας).

 

Αν είναι άλλη η ερώτηση, διατύπωσέ την λίγο πιο ξεκάθαρα για να βοηθήσουμε αν μπορούμε.

 

Hθελα απλα να σιγουρεψω αν ο τριαδικος αντιμετωπιζεται σαν ενας τελεστης η οχι επειδη εχει και το > μεσα .

Μπορει να ρωταω και χαζομαρα δεν ξερω

 

για να βαζει παντως ενα ζευγος μονο τοτε τον θεωρει σαν εναν τελεστη ολοκληρο.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Λοιπόν έχω μια ερώτηση η οποία είναι ψιλο C++.

 

Καλώ μια συνάρτηση η οποία υπολογίζει το Mahalanobis distance ανάμεσα σε 2 vectors. Σε κάποιες πράξεις οι δεκαδικοί αριθμοί είναι τόσοι πολλοί που δεν χωράνε ούτε καν σε Long Double και έχω αποτέλεσμα -1.#IND0000000...

 

Υπάρχει κάποιος τρόπος που μπορώ να το κάνω truncate απο πρίν έτσι ώστε να περιοριστεί το αποτέλεσμα σε X δεκαδικούς;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Πως θα κανεις turcate; Βασικα τι θα κανεις turcate; Για να βγαλεις infinity θα πρεπει να εχεις τερματισει την δυναμη. Αν κανεις turcate το χψ (το ψ) πως θα ξερεις για ποιον αριθμο αναφερεσαι;

 

btw Πως στο διαολο καταφερες να ορισεις δυο vectors που απεχουν λιγοτερο απο το χ ή ψ του καθε vector; Δηλαδη κατσε, η μικροτερη αποσταση ειναι το χ-χ1 ή ψ-ψ1 και η μεγαλυτερη sqrt(x22)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Βασικά το λάθος τελικά ήταν μια απόπειρα αρνητικής ρίζας...και με ένα abs φτιάχτηκε. Απλά με ξεγέλασε το -1.#IND0000. Συμβαίνουν κι αυτά ;)

Παρεπιμπτόντως έχω την εντύπωση ότι το #IND είναι "indefinable" - δεν ορίζεται δηλαδή, ενώ το #INF είναι infinity.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επειδή δεν έχω πρόσβαση σε υπολογιστή με windows μπορειτε να μου πείτε αν ο παρακάτω κώδικας ειναι σωστός;

 

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
   system("C:\Program Files\MyProgram.exe");
return 0;
}


 


 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Να κανω μια ερώτηση και εγω έστω οτι έχουμε την μακροεντολή :

 

 

 
#define GENERIC_MAX(type) \
type type##_max(type x , type y ) \
{                                \
    return x > y ? x : y;     \
}
 

 

Αν βγάλω τον τελεστή ## και αφησω σκετο το type δηλαδη type_max τοτε μετα την επεκταση απο την κλήση πχ GENERIC_MAX(long) θα είναι long type_max ( long x , long y) επειδη ο προεπεξεργαστης αντικαθιστα μονο ολοκληρα tokens και οχι τμηματα τους πχ οπως εδω που το type ειναι ενσωματωμένο μεσα σε κατι αλλο και οχι μονο του. ΣΩστα?

 

Επομενως βαζουμε τον ## για να ληφθει το type σαν να ειναι μονο του και να γινει το pasting με το _max.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Να κανω μια ερώτηση και εγω έστω οτι έχουμε την μακροεντολή :

 

 

 

 
#define GENERIC_MAX(type) \
type type##_max(type x , type y ) \
{                                \
    return x > y ? x : y;     \
}
 
 

Αν βγάλω τον τελεστή ## και αφησω σκετο το type δηλαδη type_max τοτε μετα την επεκταση απο την κλήση πχ GENERIC_MAX(long) θα είναι long type_max ( long x , long y) επειδη ο προεπεξεργαστης αντικαθιστα μονο ολοκληρα tokens και οχι τμηματα τους πχ οπως εδω που το type ειναι ενσωματωμένο μεσα σε κατι αλλο και οχι μονο του. ΣΩστα?

 

Επομενως βαζουμε τον ## για να ληφθει το type σαν να ειναι μονο του και να γινει το pasting με το _max.

 

 

Ο preprocessor αντικαθιστά ολόκληρες λέξεις και επίσης δεν αντικαθιστά λέξεις που βρίσκονται μέσα σε "". Για αυτό το λόγο υπάρχουν οι τελεστές # και ##. Μπακάλικα μπορούμε να πούμε ότι ο # δημιουργεί strings με αυτό που του δίνεις και ο ## ενώνει λέξεις δημιουργώντας μία νέα λέξη.

 

Στην προκειμένη περίπτωση όντως αυτό θα γίνει το οποίο μπορούμε πολύ εύκολα να το δούμε με τον παρακάτω κώδικα.

#define G1_MAX(type) \
type type_max(type x, type y) \
{\
	return x > y ? x : y;\
}

#define G2_MAX(type) \
type type##_max(type x, type y) \
{\
	return x > y ? x : y;\
}

G1_MAX(int)
G2_MAX(long)
Αν πετάξουμε τον παραπάνω κώδικα στον gcc καλώντας τον με την παράμετρο -E παίρνουμε
int type_max(int x, int y) { return x > y ? x : y;}
long long_max(long x, long y) { return x > y ? x : y;}
Βλέπουμε ότι στη περίπτωση του long επειδή χρησιμοποιήσαμε τον τελεστή ##, το type αντιμετωπίστηκε σαν ξεχωριστή λέξη και έτσι αντικαταστάθηκε από το long και μετά ενώθηκε με το _max.

 

Ένα παρόμοιο πρόβλημα μας λύνει και ο τελεστής # που αντιμετωπίζει αυτό που του δίνουμε σαν να ήταν string.

#define EXIT_ON_ERR(ERR)\
if (ERR) {\
	fprintf(stderr, "Error value ERR \n");\
	exit(ERR);\
}

#define EXIT_ON_ERR2(ERR)\
if (ERR) {\
	fprintf(stderr, "Error value " #ERR "\n");\
	exit(ERR);\
}

EXIT_ON_ERR(5)
EXIT_ON_ERR2(3)
if (5) { fprintf(stderr, "Error value ERR \n"); exit(5);}
if (3) { fprintf(stderr, "Error value " "3" "\n"); exit(3);}
Στον παραπάνω κώδικα (παραβλέποντας, χάριν ευκολίας, κώδικα που έπρεπε να μπει για να είναι σωστό το macro όπως πχ do-while(0), κτλ) βλέπουμε ότι ενώ το 5 αντικαταστάθηκε σωστά στην συνθήκη του if και στο όρισμα της exit, δεν αντικαταστάθηκε μέσα στο string της fprintf. Για να δουλέψει σωστά ο κώδικας, βάζουμε ξεχωριστά το ERR και με τον τελεστή # λέμε ότι θέλουμε να γίνει string. Έτσι βλέπουμε να υπάρχει σωστά αντικατάσταση του ERR με το "3" ως string.

Κατα πασα πιθανοτητα ενας compiler θα στην κανει inline, αρα ειναι pointless να εχεις τετοιο ειδους συνρατησεις.

+1

 

Στον πυρήνα του linux και γενικά σε μεγάλα project βλέπουμε συχνά τέτοια "κόλπα" με τον preprocessor γιατί η σωστή υλοποίηση με τον compiler θα ήταν πιο χρονοβόρα / άσχημη / μεγάλη / whatever. Όπως είπε και ο παπί, σε περιπτώσεις όπως την παραπάνω δεν έχει νόημα να χρησιμοποιούμε τον preprocessor. Αν και θα πέσουν κάποιοι να με φάνε, θα πω πως καλό είναι όπου υπάρχει εναλλακτική και μπορούμε να μην χρησιμοποιούμε τον preprocessor (πχ μπορούμε να χρησιμοποιήσουμε τον compiler), τότε να το κάνουμε.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπακάλικα? Για αυτο ο King έχει σε εισαγωγικά το "stringization" και το "pasting" ? για τους # και ## αντιστοιχα.

 

Οταν λεμε οτι μια συναρτηση γινεται inline τι ακριβως εννοουμε?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

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

Μπακάλικα? Για αυτο ο King έχει σε εισαγωγικά το "stringization" και το "pasting" ? για τους # και ## αντιστοιχα.

 

Οταν λεμε οτι μια συναρτηση γινεται inline τι ακριβως εννοουμε?

 

Απλά ο κώδικας της συνάρτησης αντικαθιστά το function call. Είναι σαν μέσα στο function απο όπου καλείς το inline function, απλά να είχες τον κώδικα στη θέση του function. Έτσι γλιτώνεις το function overhead....οπότε αν καλείς μια συναρτησούλα 800 φορές είναι καλό να την ορίσεις ως inline (αν και θα την κάνει ο compiler λογικά) .

Επεξ/σία από ZAKKWYLDE
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επίσης, ορίζοντας μια συνάρτηση ως inline δεν είσαι σε καμία περίπτωση σίγουρο πως όντως θα το πραγματοποιήσει ο compiler (είναι απλώς hint προς τον compiler και όχι βεβαιότητα).

Επομένως, αν ο κώδικάς μας πρόκειται να γίνει compile με διαφορετικούς compilers (είτε από εμάς είτε από τρίτους) ο μόνος τρόπος να σιγουρέψουμε πως θα γίνονται πάντα inline τα σημεία που θέλουμε, είναι να τα γράψουμε στον προεπεξεργαστή.

 

Ο πυρήνας του Linux που αναφέρθηκε, είναι κλασσικό τέτοιο παράδειγμα... όπου δηλαδή δεν είναι λογικό να επαφίενται τα κρίσιμα κομμάτια του κώδικα στις ορέξεις (ή μη) του εκάστοτε compiler.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επισκέπτης
Αυτό το θέμα είναι πλέον κλειστό για περαιτέρω απαντήσεις.

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