ما هي الطريقة الصحيحة لاستخدام printf لطباعة clock_t؟

StackOverflow https://stackoverflow.com/questions/1083142

  •  23-08-2019
  •  | 
  •  

سؤال

أنا أستخدم حاليا صريحا unsigned long long واستخدام %llu لطباعة ذلك، ولكن منذ size_t لديه %z محدد، لماذا لا clock_t لديك واحدة؟

ليس هناك حتى ماكرو لذلك. ربما أستطيع أن أفترض أنه على نظام X64 (OS و CPU) size_t هو 8 بايت في الطول (وحتى في هذه الحالة، قدموا %z)، لكن ماذا عن clock_t?

هل كانت مفيدة؟

المحلول

يبدو أن هناك ليست هناك طريقة مثالية. جذر المشكلة هو ذلك clock_t يمكن أن يكون إما عدد صحيح أو نقطة عائمة.

Clock_t يمكن أن يكون نوع نقطة عائمة

كما يذكر باستين لونارد ل posix (الذهاب فوقه)، C99 N1256 مسودة 7.23.1 / 3 يقول أيضا:

clock_t] أنواع حسابية قادرة على تمثيل الأوقات

و 6.2.5 / 18:

يتم تسمية الأنواع العالية والعوامة بشكل جماعي أنواع حسابية.

ويحدد المعيار النوع الحسابي إما أعداد صحيحة أو أنواع نقاط عائمة.

إذا كنت سوف تقسم Clocks_per_sec، استخدم طويلا

قيمة العودة clock() هو التنفيذ المحدد، والطريقة الوحيدة للحصول على معنى قياسي خارجها هو تقسيم CLOCKS_PER_SEC للعثور على عدد الثواني:

clock_t t0 = clock();
/* Work. */
clock_t t1 = clock();
printf("%Lf", (long double)(t1 - t0));

هذا جيد بما فيه الكفاية، على الرغم من أنه ليس مثاليا، والأسباب التالية:

  • يبدو أن هناك لا يتناظر intmax_t لأنواع النقطة العائمة: كيفية الحصول على أكبر نوع بيانات النقطة العائمة الدقة من الانتقاد ومحددات طباعة؟ لذلك إذا كان نوع النقطة العائمة أكبر يخرج غدا، فيمكن استخدامه وكسر تطبيقك.

  • إذا clock_t هو عدد صحيح، يلقي المقصود المعروف جيدا لاستخدام أقرب تعويم ممكن. قد تفقد الدقة، لكن الأمر لا يهم بالمقارنة مع القيمة المطلقة، ولن يحدث فقط كميات هائلة من الزمن، على سبيل المثال long int في x86 هو تعويم 80 بت مع 144 بت ذات أهمية، وهو الملايين من السنوات في ثوان.

الذهاب فوق Ummentad. من قال شيئا مشابها.

إذا كنت تفترض أنه عدد صحيح، فاستخدم٪ ju و uintmax_t

برغم من unsigned long long هو حاليا أكبر نوع عدد صحيح قياسي ممكن:

لذلك من الأفضل أن Typecast لأكبر نوع عدد صحيح غير محتمل ممكن:

#include <stdint.h>

printf("%ju", (uintmax_t)(clock_t)1);

uintmax_t مضمون للحصول على حجم أكبر حجم صحيح ممكن على الجهاز.

uintmax_t ومحدد طباعة %ju تم تقديمها في C99 و GCC على سبيل المثال تنفذها.

ككافأة، هذا يحل مرة واحدة وعلى الرغم من سؤال كيفية موثوق printf أنواع عدد صحيح (وهذا لسوء الحظ ليس هو الحال بالضرورة clock_t).

ما يمكن أن يحدث خطأ إذا كان مزدوج:

  • إذا كان كبيرا جدا لتناسب عدد صحيح، سلوك غير محدد
  • أصغر بكثير من 1، سوف تحصل على تقريب إلى 0 ولن ترى أي شيء

نظرا لأن هذه العواقب أكثر صرامة بكثير من عدد صحيح لتحويل التعويم، فمن المحتمل أن يكون استخدام تعويم فكرة أفضل.

على Glibc 2.21 إنه عدد صحيح

يقول الدليل أن استخدام double هي فكرة أفضل:

على أنظمة GNU / Linux و GNU / HURD، Clock_t تعادل Long Int و Clocks_per_sec قيمة عدد صحيح. ولكن في أنظمة أخرى، يمكن أن تكون كل من Clock_t و Clubsss_per_secs_per_sec من الماكرو كلا من أنواع عدد صحيح أو فينتيرز. تؤكد القيم الزمنية التي تمزقها وحدة المعالجة المركزية المزدوجة، كما هو الحال في المثال أعلاه، أن العمليات مثل الحساب والطباعة تعمل بشكل صحيح وباستخدامها بغض النظر عن التمثيل الأساسي.

في Glibc 2.21:

أنظر أيضا

نصائح أخرى

بقدر ما أعرف، الطريقة التي تفعلها هي الأفضل. ماعادا هذا clock_t قد يكون نوع حقيقي:

time_t و clock_t يجب أن يكون عدد صحيح أو حقيقي العائمة.

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html

ربما لأن علامات الساعة ليست وحدة محددة للغاية. يمكنك تحويله إلى ثوان وطباعته كمضاعف:

time_in_seconds = (double)time_in_clock_ticks / (double)CLOCKS_PER_SEC;
printf("%g seconds", seconds);

يتوسع الماكرو Clocks_per_sec إلى تعبير يمثل عدد علامات الساعة في الثانية.

يتعين على قيادة C إسكيع مجموعة واسعة من البنيات، مما يجعل من المستحيل جعل أي ضمانات أخرى جانبا من حقيقة أن نوع الساعة الداخلي هو حسابي.

في معظم الحالات، أنت مهتم بفواصل زمنية، لذلك قمت بتحويل الفرق في علامات الساعة إلى مللي ثانية. أ unsigned long كبير بما يكفي لتمثيل الفاصل الزمني لما يقرب من 50 يوما حتى لو كان 32 بت، لذلك يجب أن يكون كبيرا بما يكفي لمعظم الحالات:

clock_t start;
clock_t end;
unsigned long millis = (end - start) * 1000 / CLOCKS_PER_SEC;

طريقة واحدة هي باستخدام gettimeofday وظيفة. يمكن للمرء أن يجد الفرق باستخدام هذه الوظيفة:

unsigned long  diff(struct timeval second, struct timeval first)
{
    struct timeval  lapsed;
    struct timezone tzp;
    unsigned long t;

    if (first.tv_usec > second.tv_usec) {
        second.tv_usec += 1000000;
        second.tv_sec--;
    }

    lapsed.tv_usec = second.tv_usec - first.tv_usec;
    lapsed.tv_sec  = second.tv_sec  - first.tv_sec;
    t = lapsed.tv_sec*1000000 + lapsed.tv_usec;

    printf("%lu,%lu - %lu,%lu = %ld,%ld\n",
           second.tv_sec, second.tv_usec,
           first.tv_sec,  first.tv_usec,
           lapsed.tv_sec, lapsed.tv_usec);

    return t;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top