Programme C de trouver la direction de croissance de la pile
Comment puis-je trouver dans C si une pile est de progresser en avant ou en arrière ? Ce travail?
int j = 0;
int k = 0;
if (&k > &j)
printf ("Stack is growing in forward direction");
else if (&k < &j)
printf ("Stack is growing in reverse direction");
Si c'est les devoirs, vous devriez balise en tant que tel.
Vous avez oublié de fermer votre " et vous avez aussi oublié un ; :O
Nope. Mais C énigmes, je suis en train de craquer.
Est-ce que C même à propos de "la pile"? Je ne me souviens pas de quoi que ce soit de l'aborder; autant que je sache, vous pouvez avoir un C mise en œuvre qui n'utilise pas de pile, ou l'utilise de manière radicalement différente que les gens l'utiliser normalement.
Juste mort, @cHao, l'ISO ne nécessite pas de pile. Voir stackoverflow.com/questions/664744/... pour certains, intéressant à lire sur les différents systèmes, y compris celui où une liste liée émule une pile
Vous avez oublié de fermer votre " et vous avez aussi oublié un ; :O
Nope. Mais C énigmes, je suis en train de craquer.
Est-ce que C même à propos de "la pile"? Je ne me souviens pas de quoi que ce soit de l'aborder; autant que je sache, vous pouvez avoir un C mise en œuvre qui n'utilise pas de pile, ou l'utilise de manière radicalement différente que les gens l'utiliser normalement.
Juste mort, @cHao, l'ISO ne nécessite pas de pile. Voir stackoverflow.com/questions/664744/... pour certains, intéressant à lire sur les différents systèmes, y compris celui où une liste liée émule une pile
OriginalL'auteur Neel | 2011-06-21
Vous devez vous connecter pour publier un commentaire.
Pour être fiable, il faut trouver la différence entre deux appels de fonction.
Noter que ce ne sera pas vous donner une réponse sur C, mais au sujet de votre compilateur.
func
, nous sommes de retour à la case départ. Ce serait sans doute travailler dans le débogage de code sans optimisations, si vous voulez juste savoir pour le bien de la curiosité, mais je ne voudrais pas compter sur elle pour la production de code.Oui. Une mise en œuvre peut ordonner les variables locales toutefois, il souhaite dans un cadre de pile pour plus d'efficacité: stackoverflow.com/questions/6079063/... et, bien sûr, la pile ne doit pas exister du tout 🙂
Je ne dis pas qu'il le sera toujours, mais: @zneak), d'Inlining une fonction récursive serait tout un exploit. @paxdiablo, d'Après votre lien, ma variable devrait exister sur la pile.
(p < &i) invoque un comportement indéfini. Le résultat de l'application d'opérateurs relationnels pour les pointeurs n'est défini que si les pointeurs point sur les objets dans le même tableau ou de la structure.
l'ensemble du concept suppose l'vars sont dans la même pile, donc je ne serais pas inquiet à ce sujet. Cela dit, j'apprécie l'info.
OriginalL'auteur ikegami
Vous ne pouvez pas. Dans votre code,
(&k > &j)
invoque un comportement indéfini comportement. Pointeur de la comparaison avec les opérateurs relationnels n'est pas définie, sauf si les pointeurs point sur les objets dans le même tableau (ou un objet au-delà de la fin du tableau).Si une pile existe est dictée par votre mise en œuvre. Un comportement indéfini ne peut pas prédire les détails de mise en œuvre.
Le C ISO norme ne mentionne pas le mot "pile", même une fois. Une pile peut même ne pas exister. La mémoire utilisée par les appels de fonction pour garder les variables locales pourraient même ne pas être contigus.
OriginalL'auteur sigjuice
Ce n'est pas une caractéristique facile à déterminer dans C seulement parce que votre compilateur peut effectuer diverses optimisations qui peuvent se briser de tels tests. Vous feriez probablement mieux avec un assemblage de fonction.
En d'autres termes, votre fonction pourrait de travail, mais il n'est pas sûr. Et si cela ne fonctionne pas, il ne sera pas signaler une erreur: au lieu de cela, vous obtiendrez un résultat incorrect, et aucun moyen de le dire. La pile, et la gestion des conventions d'appel, sont les deux seules à faible niveau de choses que C parvient à se cacher.
Mon assembleur x86 est rouillé, mais hors de ma tête, ce (Intel syntaxe) de l'assemblée fonction pourrait donner des résultats corrects. Sa C prototype serait
int getGrowthDirection()
; elle renvoie un nombre positif si la pile grandit vers l'avant et d'un nombre négatif si la pile augmente dans le sens inverse.Notez que cette fonction est presque inutiles, comme l'assemblage nécessite de connaître la plate-forme de ciblage, et si vous connaissez la plate-forme de ciblage, alors vous devriez savoir la croissance de la pile direction.
Yup, même sans les optimisations de ce qui peut arriver.
Si l'on utilise à l'asm x86, ne pouvons-nous pas assez bien la garantie déjà que la pile augmente à la baisse?
maintenant que vous le dites, oui. C'est stupide de fonction.
OriginalL'auteur zneak
Il a déjà été souligné qu'un C l'environnement d'exécution ne sont pas nécessairement utiliser une pile (activation de la fonction de cadres peut être attribué sur un segment). Supposons donc que nous avons un système qui utilise une pile pour les variables automatiques. Ensuite, nous pourrions être en mesure de déterminer la pile de direction en comparant les adresses des variables à partir de deux d'activation différents cadres. Cependant, il y a deux problèmes avec cette approche:
Le premier problème est insoluble, si nous avons une symbolique de l'environnement d'exécution qui permet de détecter illégale d'un pointeur de comparaison au moment de l'exécution. Supposons donc que nous avons un classique de l'optimisation du compilateur qui représente les pointeurs nus adresses de la machine (quand ils ne peuvent pas être optimisés loin).
De penser à tout cela j'ai d'abord eu distrait par l'idée de convertir les pointeurs vers des entiers (C99 est uintptr_t). Mais c'est un leurre, je pense. Tout d'abord, en comparant les nombres entiers pourraient ne pas donner le même résultat que la comparaison de l'original pointeurs donc, vous devez les convertir en arrière de toute façon. Deuxièmement, nous n'essayons pas de cacher au compilateur que nous avons de la comparaison de pointeurs; nous essayons seulement de cacher le compilateur qui pointeurs que nous comparons.
J'ai trouvé, il a aidé à examiner la deuxième premier problème: comment pouvons-nous nous assurer que nous avons des pointeurs vers des variables dans les différents activation des cadres?
Laissez-nous rejeter l'idée de mettre une fonction dans une bibliothèque séparée ou dynamiquement chargé du module: ce serait non portable, et si nous allons être non-portable, alors nous pourrions aussi bien imprimer les indicateurs avec printf("%p\n", p) et de les comparer avec des utilitaires d'environnement. En plus d'être non-portable ce serait pas marrant du tout.
Pour forcer le compilateur à générer du code avec des variables locales dans l'activation des cadres que nous pourrions avoir une fonction récursive jusqu'à une profondeur qui ne peut pas être déterminé au moment de la compilation avec une variable locale qui est peut-être vivre à travers un appel récursif, et ainsi de suite. En bref, nous voulons qu'il soit très dur, de préférence impossible, pour le compilateur de déterminer ce qui va se passer au moment de l'exécution.
Il y a différentes façons dont nous pourrions faire l'exécution prévisible pour nous, mais pas clair pour le compilateur. On pourrait utiliser les mathématiques complexes ou d'un générateur de nombres pseudo-aléatoires. Cependant, il est probablement assez bon juste pour le rendre potentiellement dépendent les arguments de ligne de commande, avec le comportement que nous voulons être le comportement par défaut sans argument (en espérant que personne dans le monde réel compilateur optimise un programme en faisant interprétation symbolique avec l'hypothèse qu'il sera exécuté sans arguments). Nous avons donc pu avoir la séquence des opérations à effectuer est spécifié explicitement dans argv[1] et le programme serait une sorte de mini-interprète.
Avec cette approche, je pense que je peux répondre à la question d'origine avec le programme suivant qui essaie de portable pas utiliser de fichiers d'en-tête ou des fonctions de la bibliothèque:
Ici est une version plus longue avec des commentaires et des résultats de suivi pour expliquer comment cela fonctionne:
Remarque que j'ai à peine testé ce programme!
Qui m'a été attirée sur ce problème par un défaut de autoconf test dans la Debian "librep". Cependant, je n'hésiterais pas à recommander un pas encore été testées programme comme celui-ci pour une utilisation dans un autoconf test. Dans la pratique, je suppose qu'il est plus sûr de supposer que toutes les piles sont en descendant à moins que nous avons reconnue d'exception, tels que Debian "hppa" de l'architecture.
OriginalL'auteur Edmund Grimley Evans
Dans un Linux (ou un autre Système d'Exploitation) lorsqu'un sous-programme est appelé, la mémoire pour les variables locales vient de la pile du processus. Toute la mémoire allouée dynamiquement (à l'aide de malloc, nouvelles, etc.) provient du segment de mémoire de la zone du processus. Au cours de la récursivité de la mémoire locale est attribuée à partir de pile lors de l'appel de fonction et d'obtenir effacée lors de l'exécution de la fonction se fait.
La mémoire est représentée, avec le moins d'adresse en bas et le plus élevé étant au sommet. Voici les étapes pour trouver la direction de croissance de la pile dans la récursivité à l'aide un rapide code C.
mettre sur MAC
sortie sur ubuntu
La pile grandit vers le bas sur ces configurations mémoire les adresses sont la réduction. Cela dépend de l'architecture du système et peuvent avoir un comportement différent pour les autres architectures.
0x7fff6f9e8868
OriginalL'auteur Megharaj